def extract_slice(self, data='strain', phi=None, az_idx=None, z_idx=None): """ Extract 2D data slice wrt. azimuthal slice index or angle (phi). The extracted data is defined using the data variable (str), which must be one of the following: peaks, peaks error, fwhm, fwhm error, strain, strain error, shear strain, stress, shear stress. Certain combinations of data type and azimuthal index/phi will not work (e.g. can't extract peaks wrt. phi only wrt. az. index). Note: must define EITHER phi or az_idx Args: data (str): Data type to extract (see above) phi (float): Azimuthal angle in rad az_idx (int): Azimuthal slice index z_idx (int): Index of slice height in 3D array """ complex_check(data, self.analysis_state, phi, az_idx) command = text_cleaning(data) az_command = 'phi' if phi is not None else 'az_idx' if az_command == 'az_idx': az_idx = int(az_idx) if 'stress' not in command: data_command = { 'peaks': self.peaks, 'peaks error': self.peaks_err, 'fwhm': self.fwhm, 'fwhm error': self.fwhm_err, 'strain': self.strain, 'strain error': self.strain_err } data = data_command[command][..., az_idx] else: d = self.strain if 'err' not in command else self.strain_err e_xx, e_yy = d[..., az_idx], d[..., az90(self.phi, az_idx)] data = self.stress_eqn(e_xx, e_yy, self.E, self.v) else: tensor = self.strain_tensor tensor = tensor[..., 0], tensor[..., 1], tensor[..., 2] shear = True if 'shear' in command else False stress = True if 'stress' in command else False if shear: e_xy = shear_transformation(phi, *tensor) data = self.G * e_xy if stress else e_xy elif stress: e_xx = strain_transformation(phi, *tensor) e_yy = strain_transformation(phi + np.pi / 2, *tensor) data = self.stress_eqn(e_xx, e_yy, self.E, self.v) else: data = strain_transformation(phi, *tensor) data = data[z_idx] if z_idx is not None else data return data
def extract_slice(self, data='strain', phi=None, az_idx=None, z_idx=None): """ Extract 2D data slice wrt. azimuthal slice index or angle (phi). The extracted data is defined using the data variable (str), which must be one of the following: peaks, peaks error, fwhm, fwhm error, strain, strain error, shear strain, stress, shear stress. Certain combinations of data type and azimuthal index/phi will not work (e.g. can't extract peaks wrt. phi only wrt. az. index). Note: must define EITHER phi or az_idx Args: data (str): Data type to extract (see above) phi (float): Azimuthal angle in rad az_idx (int): Azimuthal slice index z_idx (int): Index of slice height in 3D array """ complex_check(data, self.analysis_state, phi, az_idx) command = text_cleaning(data) az_command = 'phi' if phi is not None else 'az_idx' if az_command == 'az_idx': az_idx = int(az_idx) if 'stress' not in command: data_command = {'peaks': self.peaks, 'peaks error': self.peaks_err, 'fwhm': self.fwhm, 'fwhm error': self.fwhm_err, 'strain': self.strain, 'strain error': self.strain_err} data = data_command[command][..., az_idx] else: d = self.strain if 'err' not in command else self.strain_err e_xx, e_yy = d[..., az_idx], d[..., az90(self.phi, az_idx)] data = self.stress_eqn(e_xx, e_yy, self.E, self.v) else: tensor = self.strain_tensor tensor = tensor[..., 0], tensor[..., 1], tensor[..., 2] shear = True if 'shear' in command else False stress = True if 'stress' in command else False if shear: e_xy = shear_transformation(phi, *tensor) data = self.G * e_xy if stress else e_xy elif stress: e_xx = strain_transformation(phi, *tensor) e_yy = strain_transformation(phi + np.pi / 2, *tensor) data = self.stress_eqn(e_xx, e_yy, self.E, self.v) else: data = strain_transformation(phi, *tensor) data = data[z_idx] if z_idx is not None else data return data
def test_angles(self): self.data.calculate_strain(self.q0) # Compare angles, same position for p_idx in [0, 7, 12, 26, 32]: tensor = e_xx[p_idx], e_yy[p_idx], e_xy[p_idx] initial = strain_transformation(self.data.phi, *tensor) processed = self.data.strain[p_idx] max_diff = np.abs(np.max(initial - processed)) assert max_diff < 10**-4, (p_idx, max_diff) # Brittle (linux)?!
def test_angles(self): self.data.calculate_strain(self.q0) # Compare angles, same position for p_idx in [(0, 0), (4, 4), (3, 5), (1, 2), (0, 4)]: tensor = e_xx[p_idx], e_yy[p_idx], e_xy[p_idx] initial = strain_transformation(self.data.phi, *tensor) processed = self.data.strain[p_idx] max_diff = np.abs(np.max(initial - processed)) assert max_diff < 10**-4, (p_idx, max_diff)
def test_angles(self): self.data.calculate_strain(self.q0) # Compare angles, same position for p_idx in [(0, 0), (4, 4), (3, 5), (1, 2), (0, 4)]: tensor = e_xx[p_idx], e_yy[p_idx], e_xy[p_idx] initial = strain_transformation(self.data.phi, *tensor) processed = self.data.strain[p_idx] max_diff = np.abs(np.max(initial - processed)) assert max_diff < 10 ** -4, (p_idx, max_diff)
def test_positions(self): self.data.calculate_strain(self.q0) # Compare positions, same angle for idx in [0, 7, 12, 26, 32]: tensor = e_xx, e_yy, e_xy initial = strain_transformation(self.data.phi[idx], *tensor) processed_1 = self.data.strain[..., idx] processed_2 = self.data.extract_slice(phi=self.data.phi[idx]) for processed in [processed_1, processed_2]: max_diff = np.abs(np.max(initial - processed)) assert max_diff < 10**-4, (idx, max_diff) # Brittle (linux)?!
def extract_strain_array(self, phi): """ Add valus for phi :param phi: :return: """ strain = np.nan * np.ones((self.x.shape + (1, ) + phi.shape)) for idx, tt in enumerate(phi): e_xx1 = strain_transformation(tt, self.e_xx, self.e_yy, self.e_xy) strain[:, :, 0, idx] = e_xx1 return strain
def extract_strain_array(self, phi): """ Add valus for phi :param phi: :return: """ strain = np.nan * np.ones((self.x.shape + (1,) + phi.shape)) for idx, tt in enumerate(phi): e_xx1 = strain_transformation(tt, self.e_xx, self.e_yy, self.e_xy) strain[:, :, 0, idx] = e_xx1 return strain
def plot_strain_fit(self, pnt=None, figsize=(11, 5)): """ Plots fitted in-plane strain field and tensor for given data point. Plots strain wrt. phi and associated tensor fit. The tensor fit is represented as a Mohr's circle, with e_xx, e_yy (for that point) being highlighted on both plots. Args: pnt (tuple): Define data point (index) else point (0, ) x ndim. figsize (tuple): Figure size """ pnt = (0,) * (self.strain.ndim - 1) if pnt is None else pnt fig, (ax_1, ax_2) = plt.subplots(1, 2, figsize=figsize) p = self.strain_tensor[pnt] ax_1.plot(self.phi, self.strain[pnt], 'k*') phi_2 = np.linspace(self.phi[0], self.phi[-1], 1000) ax_1.plot(phi_2, strain_transformation(phi_2, *p), 'k-', linewidth=0.5) ax_1.set_xlabel(r'$\phi$ (rad)', size=14) ax_1.set_ylabel(r'$\epsilon$', size=14) ax_1.ticklabel_format(axis='both', style='sci', scilimits=(-3, 3)) ax_2.ticklabel_format(axis='both', style='sci', scilimits=(-3, 3)) ax_2.set_xlabel(r'$\epsilon$', size=14) ax_2.set_ylabel(r'$\gamma}$', size=14) e_xx, e_yy, e_xy = self.strain_tensor[pnt] mean = (e_xx + e_yy) / 2 e_1 = mean + (e_xy**2 + ((e_xx - e_yy) / 2)**2)**0.5 e_2 = e_xx + e_yy - e_1 radius = (e_1 - e_2) / 2 for x, text in zip([self.phi[0], self.phi[0] + np.pi/2], [r'$\epsilon_{xx}$', r'$\epsilon_{yy}$']): ax_1.axvline(x, ymax=0.93, linewidth=0.5, ls='--', color='k') y = ax_1.get_ylim()[1] * 0.96 ax_1.text(x, y, text, ha='center', va='bottom') circ = plt.Circle((mean, 0), radius=radius, color='k', fill=False) ax_2.add_patch(circ) for x, y, text in zip([e_1, e_2, e_xx, e_yy], [0, 0, e_xy, -e_xy], [r'$\epsilon_{1}$', r'$\epsilon_{2}$', r'$(\epsilon_{xx}$, $\epsilon_{xy})$', r'$(\epsilon_{yy}$, $\epsilon_{yx})$']): ax_2.plot(x, y, 'k.') ax_2.annotate(' %s' % text, xy=(x, y), xytext=(x, y), ha='left') ax_2.plot([e_xx, e_yy], [e_xy, -e_xy], 'k--', linewidth=0.5) fig.tight_layout()
def plot_strain_fit(self, pnt=None, figsize=(11, 5)): """ Plots fitted in-plane strain field and tensor for given data point. Plots strain wrt. phi and associated tensor fit. The tensor fit is represented as a Mohr's circle, with e_xx, e_yy (for that point) being highlighted on both plots. Args: pnt (tuple): Define data point (index) else point (0, ) x ndim. figsize (tuple): Figure size """ pnt = (0, ) * (self.strain.ndim - 1) if pnt is None else pnt fig, (ax_1, ax_2) = plt.subplots(1, 2, figsize=figsize) p = self.strain_tensor[pnt] ax_1.plot(self.phi, self.strain[pnt], 'k*') phi_2 = np.linspace(self.phi[0], self.phi[-1], 1000) ax_1.plot(phi_2, strain_transformation(phi_2, *p), 'k-', linewidth=0.5) ax_1.set_xlabel(r'$\phi$ (rad)', size=14) ax_1.set_ylabel(r'$\epsilon$', size=14) ax_1.ticklabel_format(axis='both', style='sci', scilimits=(-3, 3)) ax_2.ticklabel_format(axis='both', style='sci', scilimits=(-3, 3)) ax_2.set_xlabel(r'$\epsilon$', size=14) ax_2.set_ylabel(r'$\gamma}$', size=14) e_xx, e_yy, e_xy = self.strain_tensor[pnt] mean = (e_xx + e_yy) / 2 e_1 = mean + (e_xy**2 + ((e_xx - e_yy) / 2)**2)**0.5 e_2 = e_xx + e_yy - e_1 radius = (e_1 - e_2) / 2 for x, text in zip([self.phi[0], self.phi[0] + np.pi / 2], [r'$\epsilon_{xx}$', r'$\epsilon_{yy}$']): ax_1.axvline(x, ymax=0.93, linewidth=0.5, ls='--', color='k') y = ax_1.get_ylim()[1] * 0.96 ax_1.text(x, y, text, ha='center', va='bottom') circ = plt.Circle((mean, 0), radius=radius, color='k', fill=False) ax_2.add_patch(circ) for x, y, text in zip([e_1, e_2, e_xx, e_yy], [0, 0, e_xy, -e_xy], [ r'$\epsilon_{1}$', r'$\epsilon_{2}$', r'$(\epsilon_{xx}$, $\epsilon_{xy})$', r'$(\epsilon_{yy}$, $\epsilon_{yx})$' ]): ax_2.plot(x, y, 'k.') ax_2.annotate(' %s' % text, xy=(x, y), xytext=(x, y), ha='left') ax_2.plot([e_xx, e_yy], [e_xy, -e_xy], 'k--', linewidth=0.5) fig.tight_layout()