### 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 ... @@ -8,4 +8,5 @@ tqdm traitlets traitlets uncertainties uncertainties uncertainties.egg uncertainties.egg pyqt5 pyqt5 \ No newline at end of file terminal-animation \ No newline at end of file
 """ Advanced data analysis functions for ringshear tester data """ """ Advanced data analysis functions for ringshear tester data """ import numpy as np import numpy as np import scipy.optimize as spopt 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 from uncertainties.core import ufloat ... @@ -25,8 +26,8 @@ def rst_analmut(x, y): ... @@ -25,8 +26,8 @@ def rst_analmut(x, y): # M = M[np.nonzero(np.isfinite(M))] # M = M[np.nonzero(np.isfinite(M))] # C = C[np.nonzero(np.isfinite(C))] # C = C[np.nonzero(np.isfinite(C))] statsM = stats.norm.fit([d.n for d in M]) statsM = spstats.norm.fit([d.n for d in M]) statsC = stats.norm.fit([d.n for d in C]) statsC = spstats.norm.fit([d.n for d in C]) uncM = ufloat(statsM, 2*statsM) uncM = ufloat(statsM, 2*statsM) uncC = ufloat(statsC, 2*statsC) uncC = ufloat(statsC, 2*statsC) fric_mut = (uncM, uncC) fric_mut = (uncM, uncC) ... @@ -80,7 +81,10 @@ def fitfric(x, a, b): ... @@ -80,7 +81,10 @@ def fitfric(x, a, b): # %%=====================VELOCITY STEPPING ANALYSIS============================ # %%=====================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 mu_app = data['shearstress']/data['normalstress'] # Apparent friction logvel = np.log10(data['velocity']) logvel = np.log10(data['velocity']) ... @@ -91,11 +95,75 @@ def vst_analysis(data): ... @@ -91,11 +95,75 @@ def vst_analysis(data): onlyfinite = np.isfinite(logvel) onlyfinite = np.isfinite(logvel) mu_app = mu_app[onlyfinite] mu_app = mu_app[onlyfinite] logvel = logvel[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, # %%=====================VELOCITY STEPPING ANALYSIS============================ logvel, def vst_analysis_alternative(data, config): mu_app """ 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)) perr = 2*np.sqrt(np.diag(pcov)) name_fit = ( name_fit = ( ... @@ -105,10 +173,36 @@ def vst_analysis(data): ... @@ -105,10 +173,36 @@ def vst_analysis(data): perr, perr, pfit, pfit, perr) 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========================== # %%======================BOOTSTRAP LINEAR REGRESSION========================== def fit_bootstrap(datax, datay, function=None, def fit_bootstrap(datax, datay, function=None, yerr_systematic=0.0, nsigma=2, nsets=100, yerr_systematic=0.0, nsigma=2, nsets=100, yerr=None): yerr=None): ... ...
 ... @@ -9,6 +9,7 @@ import operator ... @@ -9,6 +9,7 @@ import operator import os import os import shutil import shutil import animation import nptdms import nptdms import numpy as np import numpy as np import uncertainties as unc import uncertainties as unc ... @@ -19,9 +20,9 @@ from uncertainties import unumpy as unp ... @@ -19,9 +20,9 @@ from uncertainties import unumpy as unp from rstevaluation import data as rstdat from rstevaluation import data as rstdat @animation.wait() def convert(path, file_in, config): def convert(path, file_in, config): """Reads data from source files and returns a dictionary with data""" """Reads data from source files and returns a dictionary with data""" if isinstance(config, configparser.ConfigParser): if isinstance(config, configparser.ConfigParser): var = { var = { k: json.loads(config['parameters'][k]) k: json.loads(config['parameters'][k]) ... @@ -81,7 +82,6 @@ def convert(path, file_in, config): ... @@ -81,7 +82,6 @@ def convert(path, file_in, config): np.sqrt(10**2 + (data['shear_smth_nom']*0.005)**2) np.sqrt(10**2 + (data['shear_smth_nom']*0.005)**2) ) ) ) ) print(file_in+' read') print(file_in+' read') return data return data ... ...
 """ Plotting functions for rst-evaluation """ """ Plotting functions for rst-evaluation """ import os import os import animation import matplotlib.gridspec as gridspec import matplotlib.gridspec as gridspec import matplotlib.pyplot as plt import matplotlib.pyplot as plt import numpy as np import numpy as np ... @@ -12,6 +13,7 @@ from rstevaluation import analysis as rst_analysis ... @@ -12,6 +13,7 @@ from rstevaluation import analysis as rst_analysis # ===================LINEAR REGRESSION========================================= # ===================LINEAR REGRESSION========================================= @animation.wait() def plotstd(path, name, strength, fricdata): def plotstd(path, name, strength, fricdata): """ Plots the results of the linear regression """ """ Plots the results of the linear regression """ plt.rcParams['savefig.format'] = 'pdf' plt.rcParams['savefig.format'] = 'pdf' ... @@ -77,6 +79,7 @@ def plotstd(path, name, strength, fricdata): ... @@ -77,6 +79,7 @@ def plotstd(path, name, strength, fricdata): # %%======================PLOT HISTOGRAMS====================================== # %%======================PLOT HISTOGRAMS====================================== @animation.wait() def plothist(path, name, strength, data_mut): def plothist(path, name, strength, data_mut): """ Plots the result of the mutual linear regression as histograms """ """ Plots the result of the mutual linear regression as histograms """ title_mu = [ title_mu = [ ... @@ -185,6 +188,7 @@ def plothist(path, name, strength, data_mut): ... @@ -185,6 +188,7 @@ def plothist(path, name, strength, data_mut): # %%=======================PLOT TS============================================ # %%=======================PLOT TS============================================ @animation.wait() def plotts(path, name, exp_data, normal_stress): def plotts(path, name, exp_data, normal_stress): """ Plots all experiments into one plot """ """ Plots all experiments into one plot """ plt.rcParams['figure.figsize'] = (10, 8) plt.rcParams['figure.figsize'] = (10, 8) ... @@ -238,7 +242,8 @@ def plotts(path, name, exp_data, normal_stress): ... @@ -238,7 +242,8 @@ def plotts(path, name, exp_data, normal_stress): # %%=================PLOT VST ANALYSIS========================================= # %%=================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 """ """ Plots VST analysis data """ plt.rcParams['savefig.format'] = 'pdf' plt.rcParams['savefig.format'] = 'pdf' plt.rcParams['font.size'] = 10 plt.rcParams['font.size'] = 10 ... @@ -276,9 +281,10 @@ def plotVST(path, data, pfit, perr, name_fit): ... @@ -276,9 +281,10 @@ def plotVST(path, data, pfit, perr, name_fit): ax2.set_xlim(0, np.nanmax(displ) + np.nanmax(displ)/100) ax2.set_xlim(0, np.nanmax(displ) + np.nanmax(displ)/100) # shear velocity vs. fricton: # 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( ax3.plot( vel, rst_analysis.fitfric(np.log10(vel), *pfit), 10**x, rst_analysis.fitfric(x, *pfit), 'g-', 'g-', label='curve fit: ' + name_fit label='curve fit: ' + name_fit ) ) ... @@ -286,13 +292,13 @@ def plotVST(path, data, pfit, perr, 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_xlabel(r'Shear velocity $v$ [$\mathregular{mm s^{-1}}$]') ax3.set_ylabel('Friction') ax3.set_ylabel('Friction') ax3.set_xlim( ax3.set_xlim( np.nanmin(vel)-(np.nanmin(vel)/5), np.nanmin(10**x)-(np.nanmin(10**x)/5), np.nanmax(vel)+np.nanmax(vel)/5 np.nanmax(10**x)+np.nanmax(10**x)/5 ) ) ax3.legend(fontsize=8, ax3.legend(fontsize=8, facecolor='w', facecolor='w', edgecolor='k', edgecolor='k', loc='upper right', # loc='upper right', framealpha=0.5) framealpha=0.5) fname = os.path.splitext(data['name']) fname = os.path.splitext(data['name']) fig.suptitle(fname, fontsize=14, y=0.95) fig.suptitle(fname, fontsize=14, y=0.95) ... ...