def custom_violin_stats(data, weights): # Get weighted median and mean (using weighted module for median) median = weighted.quantile_1D(data, weights, 0.5) pcent_16 = weighted.quantile_1D(data, weights, 0.16) pcent_84 = weighted.quantile_1D(data, weights, 0.84) mean, sumw = np.ma.average(data, weights=list(weights), returned=True) # Use matplotlib violin_stats, which expects a function that takes in data and coords # which we get from closure above results = violin_stats(data, vdensity_with_weights(weights)) # Update result dictionary with our updated info results[0][u"mean"] = mean results[0][u"median"] = median results[0][u"pcent_16"] = pcent_16 results[0][u"pcent_84"] = pcent_84 # No need to do this, since it should be populated from violin_stats # results[0][u"min"] = np.min(data) # results[0][u"max"] = np.max(data) return results
def weighted_quantiles(data, labels, weights, return_quantiles=False): num_categories = len(labels) breaks = linspace(0, 1, num_categories + 1) quantiles = [ weighted.quantile_1D(data, weights, mybreak) for mybreak in breaks[1:] ] ret = zeros(len(data)) for i in range(0, len(quantiles) - 1): lower = quantiles[i] upper = quantiles[i + 1] ret[and_(data >= lower, data < upper)] = labels[i] if return_quantiles: return ret + 1, quantiles else: return ret + 1
def custom_violin_stats(data, weights): """Taken from https://colab.research.google.com/drive/1cSnJGKJEqbllkPbF2z0cnfdwT40sUKKR#scrollTo=RIcLIr5XJRmx""" # Get weighted median and mean (using weighted module for median) median = weighted.quantile_1D(data, weights, 0.5) mean, sumw = np.ma.average(data, weights=list(weights), returned=True) # Use matplotlib violin_stats, which expects a function that takes in data and coords # which we get from closure above results = violin_stats(data, vdensity_with_weights(weights)) # Update result dictionary with our updated info results[0][u"mean"] = mean results[0][u"median"] = median # No need to do this, since it should be populated from violin_stats # results[0][u"min"] = np.min(data) # results[0][u"max"] = np.max(data) return results
def test_weighted_median_1D_unsorted(self): # Median of the unsorted array self.assertEqual(quantile_1D(self.a1Du, self.a1Du_w, 0.5), 30) self.assertEqual(quantile_1D(self.a1Du, np.ones_like(self.a1Du), 0.5), 27.5)
def analyzeResults(self): self.matched = [] # for paired comparisons for i, f in enumerate(self.pickles): s = f.split(os.sep)[-1] if not (fnmatch.filter(itertools.chain.from_iterable(self.matched), "*" + s)): self.matched.append(fnmatch.filter(self.pickles, "*" + s)) plotname = f.replace('.pkl', '.xplt') print("\n... Analyzing results for {:s}".format(plotname)) results = febio.FebPlt(plotname) stress = np.zeros((len(self.data[f]['elements']), 3, 3), float) strain = np.copy(stress) #material element volumes mvolumes = np.zeros(len(self.data[f]['elements']), float) #spatial element volumes svolumes = np.copy(mvolumes) nnodes = len(list(results.NodeData.keys())) displacement = np.zeros((nnodes, 3)) for j, n in enumerate(self.data[f]['nodes']): tmp = results.NodeData[j + 1]['displacement'][-1, :] displacement[j, :] = [tmp[0], tmp[1], tmp[2]] pstress = [] pstressdir = [] pstrain = [] pstraindir = [] for j, e in enumerate(self.data[f]['elements']): tmp = results.ElementData[j + 1]['stress'][-1, :] stress[j, :, :] = [[tmp[0], tmp[3], tmp[5]], [tmp[3], tmp[1], tmp[4]], [tmp[5], tmp[4], tmp[2]]] #material coordinates X = np.zeros((4, 3), float) #spatial coordinates x = np.zeros((4, 3), float) for k in range(4): X[k, :] = self.data[f]['nodes'][e[k] - 1] x[k, :] = (X[k, :] + results.NodeData[e[k]]['displacement'][-1, :]) #set up tangent space W = np.zeros((6, 3), float) w = np.zeros((6, 3), float) for k, c in enumerate([(0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (1, 2)]): W[k, :] = X[c[1], :] - X[c[0], :] w[k, :] = x[c[1], :] - x[c[0], :] dX = np.zeros((6, 6), float) ds = np.zeros((6, 1), float) for k in range(6): for l in range(3): dX[k, l] = 2 * W[k, l]**2 dX[k, 3] = 4 * W[k, 0] * W[k, 1] dX[k, 4] = 4 * W[k, 1] * W[k, 2] dX[k, 5] = 4 * W[k, 0] * W[k, 2] ds[k, 0] = (np.linalg.norm(w[k, :])**2 - np.linalg.norm(W[k, :])**2) #solve for strain E = np.linalg.solve(dX, ds) #get volumes mvolumes[j] = old_div( np.abs(np.dot(W[0, :], np.cross(W[1, :], W[2, :]))), 6.0) svolumes[j] = old_div( np.abs(np.dot(w[0, :], np.cross(w[1, :], w[2, :]))), 6.0) strain[j, :, :] = [[E[0], E[3], E[5]], [E[3], E[1], E[4]], [E[5], E[4], E[2]]] #eigenvalues and eigenvectors of stress and strain tensors #eigenvectors are normalized eigstrain, eigstraindir = np.linalg.eigh(strain[j, :, :]) order = np.argsort(eigstrain) eigstrain = eigstrain[order] eigstraindir /= np.linalg.norm(eigstraindir, axis=0, keepdims=True) eigstraindir = eigstraindir[:, order] pstrain.append(eigstrain) pstraindir.append(eigstraindir) eigstress, eigstressdir = np.linalg.eigh(stress[j, :, :]) order = np.argsort(eigstress) eigstress = eigstress[order] eigstressdir /= np.linalg.norm(eigstressdir, axis=0, keepdims=True) eigstressdir = eigstressdir[:, order] pstress.append(eigstress) pstressdir.append(eigstressdir) pstress = np.array(pstress) pstressdir = np.array(pstressdir) pstrain = np.array(pstrain) pstraindir = np.array(pstraindir) #save reference volumes self.volumes.update({f: mvolumes}) self.results['Effective Strain (von Mises)'].update({ f: np.sqrt( old_div(((pstrain[:, 2] - pstrain[:, 1])**2 + (pstrain[:, 1] - pstrain[:, 0])**2 + (pstrain[:, 2] - pstrain[:, 0])**2), 2.0)) }) self.results['Maximum Compressive Strain'].update( {f: np.outer(pstrain[:, 0], [1, 1, 1]) * pstraindir[:, :, 0]}) self.results['Maximum Tensile Strain'].update( {f: np.outer(pstrain[:, 2], [1, 1, 1]) * pstraindir[:, :, 2]}) self.results['Maximum Shear Strain'].update( {f: 0.5 * (pstrain[:, 2] - pstrain[:, 0])}) self.results['Volumetric Strain'].update( {f: old_div(svolumes, mvolumes) - 1.0}) self.results['Effective Stress (von Mises)'].update({ f: np.sqrt( old_div(((pstress[:, 2] - pstress[:, 1])**2 + (pstress[:, 1] - pstress[:, 0])**2 + (pstress[:, 2] - pstress[:, 0])**2), 2.0)) }) self.results['Maximum Compressive Stress'].update( {f: np.outer(pstress[:, 0], [1, 1, 1]) * pstressdir[:, :, 0]}) self.results['Maximum Tensile Stress'].update( {f: np.outer(pstress[:, 2], [1, 1, 1]) * pstressdir[:, :, 2]}) self.results['Maximum Shear Stress'].update( {f: 0.5 * (pstress[:, 2] - pstress[:, 0])}) self.results['Pressure'].update( {f: old_div(np.sum(pstress, axis=1), 3.0)}) self.results['Displacement'].update({f: displacement}) for i, k in enumerate(self.outputs.keys()): if self.outputs[k].get(): for m in self.matched: weights = old_div(self.volumes[m[0]], np.sum(self.volumes[m[0]])) for j, f in enumerate(m): if len(self.results[k][f].shape) > 1: dat = np.ravel( np.linalg.norm(self.results[k][f], axis=1)) else: dat = np.ravel(self.results[k][f]) if self.analysis['Generate Histograms'].get(): IQR = np.subtract(*np.percentile(dat, [75, 25])) nbins = (int( old_div( np.ptp(dat), (2 * IQR * dat.size**(old_div(-1., 3.)))))) h = histogram(dat, numbins=nbins, weights=weights) bins = np.linspace(h[1], h[1] + h[2] * nbins, nbins, endpoint=False) self.histograms[k][f] = { 'bins': bins, 'heights': h[0], 'width': h[2] } if self.analysis['Tukey Boxplots'].get(): quantiles = np.zeros(3, float) for n, q in enumerate([0.25, 0.5, 0.75]): quantiles[n] = quantile_1D(dat, weights, q) self.boxwhiskers[k][f] = { 'quantiles': quantiles, 'data': dat } if self.analysis['Calculate Differences'].get(): for c in itertools.combinations(m, 2): if len(self.results[k][c[0]].shape) > 1: dat1 = np.ravel( np.linalg.norm(self.results[k][c[0]], axis=1)) dat2 = np.ravel( np.linalg.norm(self.results[k][c[1]], axis=1)) else: dat1 = np.ravel(self.results[k][c[0]]) dat2 = np.ravel(self.results[k][c[1]]) difference = dat2 - dat1 wrms = np.sqrt( np.average(difference**2, weights=weights)) self.differences[k][c[1] + "MINUS" + c[0]] = { 'difference': difference, 'weighted RMS': wrms } self.saveResults() print("... ... Analysis Complete")
def analyzeResults(self): self.matched = [] # for paired comparisons for i, f in enumerate(self.pickles): s = f.split(os.sep)[-1] if not(fnmatch.filter( itertools.chain.from_iterable(self.matched), "*" + s)): self.matched.append(fnmatch.filter(self.pickles, "*" + s)) plotname = f.replace('.pkl', '.xplt') print("\n... Analyzing results for {:s}".format(plotname)) results = febio.FebPlt(plotname) stress = np.zeros((len(self.data[f]['elements']), 3, 3), float) strain = np.copy(stress) #material element volumes mvolumes = np.zeros(len(self.data[f]['elements']), float) #spatial element volumes svolumes = np.copy(mvolumes) nnodes = len(list(results.NodeData.keys())) displacement = np.zeros((nnodes, 3)) for j, n in enumerate(self.data[f]['nodes']): tmp = results.NodeData[j + 1]['displacement'][-1, :] displacement[j, :] = [tmp[0], tmp[1], tmp[2]] pstress = [] pstressdir = [] pstrain = [] pstraindir = [] for j, e in enumerate(self.data[f]['elements']): tmp = results.ElementData[j + 1]['stress'][-1, :] stress[j, :, :] = [[tmp[0], tmp[3], tmp[5]], [tmp[3], tmp[1], tmp[4]], [tmp[5], tmp[4], tmp[2]]] #material coordinates X = np.zeros((4, 3), float) #spatial coordinates x = np.zeros((4, 3), float) for k in range(4): X[k, :] = self.data[f]['nodes'][e[k] - 1] x[k, :] = (X[k, :] + results.NodeData[e[k]]['displacement'][-1, :]) #set up tangent space W = np.zeros((6, 3), float) w = np.zeros((6, 3), float) for k, c in enumerate( [(0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (1, 2)]): W[k, :] = X[c[1], :] - X[c[0], :] w[k, :] = x[c[1], :] - x[c[0], :] dX = np.zeros((6, 6), float) ds = np.zeros((6, 1), float) for k in range(6): for l in range(3): dX[k, l] = 2 * W[k, l] ** 2 dX[k, 3] = 4 * W[k, 0] * W[k, 1] dX[k, 4] = 4 * W[k, 1] * W[k, 2] dX[k, 5] = 4 * W[k, 0] * W[k, 2] ds[k, 0] = (np.linalg.norm(w[k, :]) ** 2 - np.linalg.norm(W[k, :]) ** 2) #solve for strain E = np.linalg.solve(dX, ds) #get volumes mvolumes[j] = old_div(np.abs( np.dot(W[0, :], np.cross(W[1, :], W[2, :]))), 6.0) svolumes[j] = old_div(np.abs( np.dot(w[0, :], np.cross(w[1, :], w[2, :]))), 6.0) strain[j, :, :] = [[E[0], E[3], E[5]], [E[3], E[1], E[4]], [E[5], E[4], E[2]]] #eigenvalues and eigenvectors of stress and strain tensors #eigenvectors are normalized eigstrain, eigstraindir = np.linalg.eigh(strain[j, :, :]) order = np.argsort(eigstrain) eigstrain = eigstrain[order] eigstraindir /= np.linalg.norm(eigstraindir, axis=0, keepdims=True) eigstraindir = eigstraindir[:, order] pstrain.append(eigstrain) pstraindir.append(eigstraindir) eigstress, eigstressdir = np.linalg.eigh(stress[j, :, :]) order = np.argsort(eigstress) eigstress = eigstress[order] eigstressdir /= np.linalg.norm(eigstressdir, axis=0, keepdims=True) eigstressdir = eigstressdir[:, order] pstress.append(eigstress) pstressdir.append(eigstressdir) pstress = np.array(pstress) pstressdir = np.array(pstressdir) pstrain = np.array(pstrain) pstraindir = np.array(pstraindir) #save reference volumes self.volumes.update({f: mvolumes}) self.results['Effective Strain (von Mises)'].update( {f: np.sqrt(old_div(((pstrain[:, 2] - pstrain[:, 1]) ** 2 + (pstrain[:, 1] - pstrain[:, 0]) ** 2 + (pstrain[:, 2] - pstrain[:, 0]) ** 2), 2.0))}) self.results['Maximum Compressive Strain'].update( {f: np.outer(pstrain[:, 0], [1 , 1, 1]) * pstraindir[:, :, 0]}) self.results['Maximum Tensile Strain'].update( {f: np.outer(pstrain[:, 2], [1, 1, 1]) * pstraindir[:, :, 2]}) self.results['Maximum Shear Strain'].update( {f: 0.5 * (pstrain[:, 2] - pstrain[:, 0])}) self.results['Volumetric Strain'].update( {f: old_div(svolumes, mvolumes) - 1.0}) self.results['Effective Stress (von Mises)'].update( {f: np.sqrt(old_div(((pstress[:, 2] - pstress[:, 1]) ** 2 + (pstress[:, 1] - pstress[:, 0]) ** 2 + (pstress[:, 2] - pstress[:, 0]) ** 2), 2.0))}) self.results['Maximum Compressive Stress'].update( {f: np.outer(pstress[:, 0], [1 , 1, 1]) * pstressdir[:, :, 0]}) self.results['Maximum Tensile Stress'].update( {f: np.outer(pstress[:, 2], [1, 1, 1]) * pstressdir[:, :, 2]}) self.results['Maximum Shear Stress'].update( {f: 0.5 * (pstress[:, 2] - pstress[:, 0])}) self.results['Pressure'].update( {f: old_div(np.sum(pstress, axis=1), 3.0)}) self.results['Displacement'].update({f: displacement}) for i, k in enumerate(self.outputs.keys()): if self.outputs[k].get(): for m in self.matched: weights = old_div(self.volumes[m[0]], np.sum(self.volumes[m[0]])) for j, f in enumerate(m): if len(self.results[k][f].shape) > 1: dat = np.ravel(np.linalg.norm(self.results[k][f], axis=1)) else: dat = np.ravel(self.results[k][f]) if self.analysis['Generate Histograms'].get(): IQR = np.subtract(*np.percentile(dat, [75, 25])) nbins = (int(old_div(np.ptp(dat), (2 * IQR * dat.size ** (old_div(-1., 3.)))))) h = histogram(dat, numbins=nbins, weights=weights) bins = np.linspace(h[1], h[1] + h[2] * nbins, nbins, endpoint=False) self.histograms[k][f] = {'bins': bins, 'heights': h[0], 'width': h[2]} if self.analysis['Tukey Boxplots'].get(): quantiles = np.zeros(3, float) for n, q in enumerate([0.25, 0.5, 0.75]): quantiles[n] = quantile_1D(dat, weights, q) self.boxwhiskers[k][f] = {'quantiles': quantiles, 'data': dat} if self.analysis['Calculate Differences'].get(): for c in itertools.combinations(m, 2): if len(self.results[k][c[0]].shape) > 1: dat1 = np.ravel(np.linalg.norm(self.results[k][c[0]], axis=1)) dat2 = np.ravel(np.linalg.norm(self.results[k][c[1]], axis=1)) else: dat1 = np.ravel(self.results[k][c[0]]) dat2 = np.ravel(self.results[k][c[1]]) difference = dat2 - dat1 wrms = np.sqrt(np.average(difference ** 2, weights=weights)) self.differences[k][c[1] + "MINUS" + c[0]] = { 'difference': difference, 'weighted RMS': wrms} self.saveResults() print("... ... Analysis Complete")