### Updated VST Analysis #8

- Implemented solution by E.Kosari using means between peaks and troughs
- New method is enabled via 'Stick-Slip-Detection'
- Fitting for VST tests now uses percentiles instead of raw datapoints
- Customization with new options
- Added dot animation while waiting for tasks
parent d69eb534
 ... ... @@ -8,4 +8,5 @@ tqdm traitlets uncertainties uncertainties.egg pyqt5 \ No newline at end of file pyqt5 terminal-animation \ No newline at end of file
 """ Advanced data analysis functions for ringshear tester data """ import numpy as np import scipy.optimize as spopt import scipy.stats as stats import scipy.signal as spsig import scipy.stats as spstats from uncertainties.core import ufloat ... ... @@ -25,8 +26,8 @@ def rst_analmut(x, y): # M = M[np.nonzero(np.isfinite(M))] # C = C[np.nonzero(np.isfinite(C))] statsM = stats.norm.fit([d.n for d in M]) statsC = stats.norm.fit([d.n for d in C]) statsM = spstats.norm.fit([d.n for d in M]) statsC = spstats.norm.fit([d.n for d in C]) uncM = ufloat(statsM, 2*statsM) uncC = ufloat(statsC, 2*statsC) fric_mut = (uncM, uncC) ... ... @@ -80,7 +81,10 @@ def fitfric(x, a, b): # %%=====================VELOCITY STEPPING ANALYSIS============================ def vst_analysis(data): def vst_analysis(data, config): """ Simply fits the apparent friction with the current loading velocity. """ mu_app = data['shearstress']/data['normalstress'] # Apparent friction logvel = np.log10(data['velocity']) ... ... @@ -91,11 +95,75 @@ def vst_analysis(data): onlyfinite = np.isfinite(logvel) mu_app = mu_app[onlyfinite] logvel = logvel[onlyfinite] # Remove values where logvel < -4 mu_app = mu_app[logvel >= -4] logvel = logvel[logvel >= -4] pfit, pcov, x, y = vst_fit( fitfric, logvel, mu_app, config ) perr = 2*np.sqrt(np.diag(pcov)) name_fit = ( r'y = ({:.4f}$\pm${:.5f})log10(x) +' + '\n\t\t' + r'({:.4f}$\pm${:.5f})').format(pfit, perr, pfit, perr) return pfit, perr, name_fit, logvel, mu_app, x, y pfit, pcov = spopt.curve_fit( fitfric, logvel, mu_app # %%=====================VELOCITY STEPPING ANALYSIS============================ def vst_analysis_alternative(data, config): """ Alternative method for fitting apparent friction provided by E. Kosari when the data shows strong stick-slip. First the stick-slip events are detected with peak detection. Then the peaks are fit with a log-linear equation. """ mu_app = data['shearstress']/data['normalstress'] # Apparent friction logvel = np.log10(data['velocity']) peaks = spsig.find_peaks( mu_app, prominence=config.getfloat('parameters', 'peak_prominence') ).tolist() troughs = spsig.find_peaks( -mu_app, prominence=config.getfloat('parameters', 'peak_prominence') ).tolist() # If the first trough is before a peak delete it while troughs < peaks: troughs.pop(0) # Remove peaks if they are not followed by a trough: while peaks[-1] > troughs[-1]: peaks.pop(-1) if len(peaks) != len(troughs): troughs = [ troughs[int(np.argwhere(p < np.array(troughs)))] for p in peaks ] # Calculate means for fitting mu_app_fit = np.array( [(mu_app[p] + mu_app[t])/2 for p, t in zip(peaks, troughs)] ) logvel_fit = logvel[peaks] # Remove nonfinite values for fitting onlyfinite = np.isfinite(mu_app_fit) mu_app_fit = mu_app_fit[onlyfinite] logvel_fit = logvel_fit[onlyfinite] onlyfinite = np.isfinite(logvel_fit) mu_app_fit = mu_app_fit[onlyfinite] logvel_fit = logvel_fit[onlyfinite] # Remove values where logvel < -4 mu_app_fit = mu_app_fit[logvel_fit >= -4] logvel_fit = logvel_fit[logvel_fit >= -4] # Do fitting pfit, pcov, x, y = vst_fit( fitfric, logvel_fit, mu_app_fit, config ) perr = 2*np.sqrt(np.diag(pcov)) name_fit = ( ... ... @@ -105,10 +173,36 @@ def vst_analysis(data): perr, pfit, perr) return pfit, perr, name_fit return pfit, perr, name_fit, logvel_fit, mu_app_fit, x, y def vst_fit(fitfunc, logvel, mu_app, config): """ Takes a special subsample per velocity step. """ vel_round = np.around(logvel, config.getint('parameters', 'vel_accuracy')) vel_un = np.unique(vel_round) # sample_counts = [len(np.argwhere(vel_round == v)) for v in vel_un] # min_samples = np.min(sample_counts) x = [] y = [] prct = np.linspace(1, 99, config.getint('parameters', 'fit_percentiles')) for vu in vel_un: # selection = np.argwhere(vel_round == vu)[:min_samples] # x.extend(vel_round[selection]) # y.extend(mu_app[selection]) selection = mu_app[np.argwhere(vel_round == vu)] for p in prct: x.append(vu) y.append(np.percentile(selection, p)) x = np.squeeze(np.array(x)) y = np.squeeze(np.array(y)) pfit, pcov = spopt.curve_fit(fitfunc, x, y) return pfit, pcov, x, y # %%======================BOOTSTRAP LINEAR REGRESSION========================== def fit_bootstrap(datax, datay, function=None, yerr_systematic=0.0, nsigma=2, nsets=100, yerr=None): ... ...
 ... ... @@ -9,6 +9,7 @@ import operator import os import shutil import animation import nptdms import numpy as np import uncertainties as unc ... ... @@ -19,9 +20,9 @@ from uncertainties import unumpy as unp from rstevaluation import data as rstdat @animation.wait() def convert(path, file_in, config): """Reads data from source files and returns a dictionary with data""" if isinstance(config, configparser.ConfigParser): var = { k: json.loads(config['parameters'][k]) ... ... @@ -81,7 +82,6 @@ def convert(path, file_in, config): np.sqrt(10**2 + (data['shear_smth_nom']*0.005)**2) ) ) print(file_in+' read') return data ... ...
 """ Plotting functions for rst-evaluation """ import os import animation import matplotlib.gridspec as gridspec import matplotlib.pyplot as plt import numpy as np ... ... @@ -12,6 +13,7 @@ from rstevaluation import analysis as rst_analysis # ===================LINEAR REGRESSION========================================= @animation.wait() def plotstd(path, name, strength, fricdata): """ Plots the results of the linear regression """ plt.rcParams['savefig.format'] = 'pdf' ... ... @@ -77,6 +79,7 @@ def plotstd(path, name, strength, fricdata): # %%======================PLOT HISTOGRAMS====================================== @animation.wait() def plothist(path, name, strength, data_mut): """ Plots the result of the mutual linear regression as histograms """ title_mu = [ ... ... @@ -185,6 +188,7 @@ def plothist(path, name, strength, data_mut): # %%=======================PLOT TS============================================ @animation.wait() def plotts(path, name, exp_data, normal_stress): """ Plots all experiments into one plot """ plt.rcParams['figure.figsize'] = (10, 8) ... ... @@ -238,7 +242,8 @@ def plotts(path, name, exp_data, normal_stress): # %%=================PLOT VST ANALYSIS========================================= def plotVST(path, data, pfit, perr, name_fit): @animation.wait() def plotVST(path, data, pfit, perr, name_fit, x, y, xq, yq): """ Plots VST analysis data """ plt.rcParams['savefig.format'] = 'pdf' plt.rcParams['font.size'] = 10 ... ... @@ -276,9 +281,10 @@ def plotVST(path, data, pfit, perr, name_fit): ax2.set_xlim(0, np.nanmax(displ) + np.nanmax(displ)/100) # shear velocity vs. fricton: ax3.plot(vel, fric, 'k.', ms=2, rasterized=True) ax3.plot(10**x, y, 'k.', ms=2, rasterized=True, label='original data') ax3.plot(10**xq, yq, 'r.', ms=2, rasterized=True, label='fit data') ax3.plot( vel, rst_analysis.fitfric(np.log10(vel), *pfit), 10**x, rst_analysis.fitfric(x, *pfit), 'g-', label='curve fit: ' + name_fit ) ... ... @@ -286,13 +292,13 @@ def plotVST(path, data, pfit, perr, name_fit): ax3.set_xlabel(r'Shear velocity $v$ [$\mathregular{mm s^{-1}}$]') ax3.set_ylabel('Friction') ax3.set_xlim( np.nanmin(vel)-(np.nanmin(vel)/5), np.nanmax(vel)+np.nanmax(vel)/5 np.nanmin(10**x)-(np.nanmin(10**x)/5), np.nanmax(10**x)+np.nanmax(10**x)/5 ) ax3.legend(fontsize=8, facecolor='w', edgecolor='k', loc='upper right', # loc='upper right', framealpha=0.5) fname = os.path.splitext(data['name']) fig.suptitle(fname, fontsize=14, y=0.95) ... ...