def get_kmap(self, E_kin=30, dk=0.03, phi=0, theta=0, psi=0, Ak_type='no', polarization='p', alpha=60, beta=90, gamma=0, symmetrization='no'): """Returns a kmap slice from the orbital data. Args: E_kin (float): Kinetic energy in eV. dk (float): Desired k-resolution in kmap in Angstroem^-1. phi (float): Euler orientation angle phi in degree. theta (float): Euler orientation angle theta in degree. psi (float): Euler orientation angle psi in degree. Ak_type (string): Treatment of |A.k|^2: either 'no', 'toroid', 'NanoESCA', 'only-toroid' or 'only-NanoESCA'. polarization (string): Either 'p', 's', 'unpolarized', 'C+', 'C-' or 'CDAD'. alpha (float): Angle of incidence plane in degree. beta (float): Azimuth of incidence plane in degree. gamma (float/str): Damping factor for final state in Angstroem^-1. str = 'auto' sets gamms automatically symmetrization (str): either 'no', '2-fold', '2-fold+mirror', '3-fold', '3-fold+mirror','4-fold', '4-fold+mirror' Returns: (PlotData): PlotData containing the kmap slice. """ # Compute new hemispherical cut if E_kin or dk has changed new_cut = self.check_new_cut(E_kin, dk) if new_cut: self.set_kinetic_energy(E_kin, dk) # Rotate molecule (that is, rotate hemisphere) if angles have changed # ... and symmetrize kmap if necessary new_orientation = self.check_new_orientation(phi, theta, psi) new_symmetrization = self.check_new_symmetrization(symmetrization) if new_symmetrization or new_orientation: self.set_orientation(phi, theta, psi) self.set_symmetry(symmetrization) # Compute polarization factor if parameters have changed new_Ak = self.check_new_Ak(Ak_type, polarization, alpha, beta, gamma) if new_cut or new_Ak: self.set_polarization(Ak_type, polarization, alpha, beta, gamma) if Ak_type == 'only-toroid' or Ak_type == 'only-NanoESCA': return PlotData(self.Ak['data'], self.kmap['krange']) else: return PlotData(self.Ak['data'] * self.kmap['data'], self.kmap['krange'])
def test_incorrect_sub(self): data = [[7, 8, 9], [10, 11, 12]] range_ = [[1, 3], [-1, 1]] second_plot_data = PlotData(data, range_) self.assertRaises(ValueError, self.plot_data.__sub__, second_plot_data) self.assertRaises(TypeError, self.plot_data.__sub__, 'string')
def change_polarization(self, Ak_type='no', polarization='p', alpha=60, beta=90, gamma=0): self.set_polarization(Ak_type, polarization, alpha, beta, gamma) return PlotData(self.Ak['data'] * self.kmap['data'], self.kmap['krange'])
def test_add(self): data = [[7, 8, 9], [10, 11, 12]] range_ = [[1, 2], [-1, 1]] second_plot_data = PlotData(data, range_) added_plot_data = self.plot_data + second_plot_data npt.assert_equal(added_plot_data.data, [[8, 10, 12], [14, 16, 18]]) added_plot_data = self.plot_data + 4 npt.assert_equal(added_plot_data.data, [[5, 6, 7], [8, 9, 10]])
def test_correct_initialization(self): npt.assert_equal(self.plot_data.data, self.data) npt.assert_equal(self.plot_data.range, self.range_) npt.assert_equal(self.plot_data.data.shape, (2, 3)) npt.assert_equal(self.plot_data.x_axis, [1., 1.5, 2.]) npt.assert_equal(self.plot_data.y_axis, [-1., 1.]) npt.assert_equal(self.plot_data.step_size, [0.5, 2.]) self.data = [[1, 2, np.nan], [4, np.inf, 6]] plot_data = PlotData(self.data, self.range_) npt.assert_equal(plot_data.data, [[1, 2, np.nan], [4, np.nan, 6]])
def test_mul(self): data = [[2, 2, 2], [3, 3, 3]] range_ = [[1, 2], [-1, 1]] second_plot_data = PlotData(data, range_) mul_plot_data = self.plot_data * second_plot_data npt.assert_equal(mul_plot_data.data, [[2, 4, 6], [12, 15, 18]]) mul_plot_data = second_plot_data * self.plot_data npt.assert_equal(mul_plot_data.data, [[2, 4, 6], [12, 15, 18]]) mul_plot_data = self.plot_data * 4 npt.assert_equal(mul_plot_data.data, [[4, 8, 12], [16, 20, 24]])
def test_sub(self): data = [[7, 8, 9], [10, 11, 12]] range_ = [[1, 2], [-1, 1]] second_plot_data = PlotData(data, range_) subed_plot_data = self.plot_data - second_plot_data npt.assert_equal(subed_plot_data.data, [[-6, -6, -6], [-6, -6, -6]]) subed_plot_data = self.plot_data - np.array(data) npt.assert_equal(subed_plot_data.data, [[-6, -6, -6], [-6, -6, -6]]) subed_plot_data = self.plot_data - 4 npt.assert_equal(subed_plot_data.data, [[-3, -2, -1], [0, 1, 2]])
def slice_from_index(self, index, axis=0): if axis == 0: data = self.data[index, :, :] range_ = [self.axes[2].range, self.axes[1].range] elif axis == 1: data = self.data[:, index, :] range_ = [self.axes[2].range, self.axes[0].range] elif axis == 2: data = self.data[:, :, index] range_ = [self.axes[1].range, self.axes[0].range] else: raise ValueError('axis has to be between 1 and 3') return PlotData(data, range_)
# kMap.py Imports from kmap.library.plotdata import PlotData from kmap.model.crosshair_model import CrosshairAnnulusModel # This script demonstrates the working and functionality for crosshairs # in kmap on a simple 9x11 grid. # New Crosshair x, y, radius, width = 0, 0, 1.5, 1.5 crosshair = CrosshairAnnulusModel(x=x, y=y, radius=radius, width=width) # Use 7x7 as data from which we cut to better demonstrate working # The data goes from 0-49 and the pixel center acts is the whole number global data data = PlotData(np.reshape(np.array(range(99)), (9, 11)), [[-5, 5], [-4, 4]]) global extent extent = data.range.flatten() + [-0.5, 0.5, -0.5, 0.5] export = {} def plot(axis, x, y, r, w, region, inverted, title=''): # Helper Function plotting crosshair and data # Set Crosshair crosshair.x = x crosshair.y = y crosshair.radius = r crosshair.width = w
def setUp(self): self.data = [[1, 2, 3], [4, 5, 6]] self.range_ = [[1, 2], [-1, 1]] self.plot_data = PlotData(self.data, self.range_)
class TestPlotData(unittest.TestCase): def setUp(self): self.data = [[1, 2, 3], [4, 5, 6]] self.range_ = [[1, 2], [-1, 1]] self.plot_data = PlotData(self.data, self.range_) def test_correct_initialization(self): npt.assert_equal(self.plot_data.data, self.data) npt.assert_equal(self.plot_data.range, self.range_) npt.assert_equal(self.plot_data.data.shape, (2, 3)) npt.assert_equal(self.plot_data.x_axis, [1., 1.5, 2.]) npt.assert_equal(self.plot_data.y_axis, [-1., 1.]) npt.assert_equal(self.plot_data.step_size, [0.5, 2.]) self.data = [[1, 2, np.nan], [4, np.inf, 6]] plot_data = PlotData(self.data, self.range_) npt.assert_equal(plot_data.data, [[1, 2, np.nan], [4, np.nan, 6]]) def test_incorrect_data_shape(self): self.data = [1, 2, 3, 4, 5, 6] self.assertRaises(TypeError, PlotData, self.data, self.range_) def test_too_small_data(self): self.data = [[1], [2]] self.assertRaises(TypeError, PlotData, self.data, self.range_) def test_incorrect_range_shape(self): self.range_ = [[1, 2]] self.assertRaises(TypeError, PlotData, self.data, self.range_) def test_incorrect_range_values(self): self.range_ = [[1, 2], [np.nan, 1]] self.assertRaises(ValueError, PlotData, self.data, self.range_) self.range_ = [[1, 2], [np.inf, 1]] self.assertRaises(ValueError, PlotData, self.data, self.range_) def test_basic_interpolation(self): new_x_axis = [1.5, 2] new_y_axis = [-0.5, 0, 0.5] new_data = self.plot_data.interpolate(new_x_axis, new_y_axis) npt.assert_equal(new_data.data, [[2.75, 3.75], [3.5, 4.5], [4.25, 5.25]]) npt.assert_equal(self.plot_data.data, self.data) new_x_axis = [-2, 1] new_y_axis = [0, -0.5, -10] new_data = self.plot_data.interpolate(new_x_axis, new_y_axis) npt.assert_equal(new_data.data, [[np.nan, 2.5], [np.nan, 1.75], [np.nan, np.nan]]) new_x_axis = [1, 1.25, 1.5, 2] new_y_axis = [-1, -0.25, 0.5, 1] new_data = self.plot_data.interpolate(new_x_axis, new_y_axis) npt.assert_equal(new_data.data, [[1., 1.5, 2., 3.], [2.125, 2.625, 3.125, 4.125], [3.25, 3.75, 4.25, 5.25], [4., 4.5, 5., 6.]]) def test_update_interpolation(self): new_x_axis = [1.5, 2] new_y_axis = [-0.5, 0, 0.5] new_data = self.plot_data.interpolate(new_x_axis, new_y_axis, update=True) npt.assert_equal(new_data.data, [[2.75, 3.75], [3.5, 4.5], [4.25, 5.25]]) npt.assert_equal(self.plot_data.data, [[2.75, 3.75], [3.5, 4.5], [4.25, 5.25]]) def test_increase_range(self): new_x_axis = [0, 1, 2, 3] new_y_axis = [-1, 0, 1, 2] new_data = self.plot_data.interpolate(new_x_axis, new_y_axis, update=True) npt.assert_equal( new_data.data, [[np.nan, 1., 3., np.nan], [np.nan, 2.5, 4.5, np.nan], [np.nan, 4., 6., np.nan], [np.nan, np.nan, np.nan, np.nan]]) npt.assert_equal(self.plot_data.x_axis, [0, 1, 2, 3]) npt.assert_equal(self.plot_data.y_axis, [-1, 0, 1, 2]) def test_add(self): data = [[7, 8, 9], [10, 11, 12]] range_ = [[1, 2], [-1, 1]] second_plot_data = PlotData(data, range_) added_plot_data = self.plot_data + second_plot_data npt.assert_equal(added_plot_data.data, [[8, 10, 12], [14, 16, 18]]) added_plot_data = self.plot_data + 4 npt.assert_equal(added_plot_data.data, [[5, 6, 7], [8, 9, 10]]) def test_incorrect_add(self): data = [[7, 8, 9], [10, 11, 12]] range_ = [[1, 3], [-1, 1]] second_plot_data = PlotData(data, range_) self.assertRaises(ValueError, self.plot_data.__add__, second_plot_data) self.assertRaises(TypeError, self.plot_data.__add__, 'string') def test_sub(self): data = [[7, 8, 9], [10, 11, 12]] range_ = [[1, 2], [-1, 1]] second_plot_data = PlotData(data, range_) subed_plot_data = self.plot_data - second_plot_data npt.assert_equal(subed_plot_data.data, [[-6, -6, -6], [-6, -6, -6]]) subed_plot_data = self.plot_data - np.array(data) npt.assert_equal(subed_plot_data.data, [[-6, -6, -6], [-6, -6, -6]]) subed_plot_data = self.plot_data - 4 npt.assert_equal(subed_plot_data.data, [[-3, -2, -1], [0, 1, 2]]) def test_incorrect_sub(self): data = [[7, 8, 9], [10, 11, 12]] range_ = [[1, 3], [-1, 1]] second_plot_data = PlotData(data, range_) self.assertRaises(ValueError, self.plot_data.__sub__, second_plot_data) self.assertRaises(TypeError, self.plot_data.__sub__, 'string') def test_mul(self): data = [[2, 2, 2], [3, 3, 3]] range_ = [[1, 2], [-1, 1]] second_plot_data = PlotData(data, range_) mul_plot_data = self.plot_data * second_plot_data npt.assert_equal(mul_plot_data.data, [[2, 4, 6], [12, 15, 18]]) mul_plot_data = second_plot_data * self.plot_data npt.assert_equal(mul_plot_data.data, [[2, 4, 6], [12, 15, 18]]) mul_plot_data = self.plot_data * 4 npt.assert_equal(mul_plot_data.data, [[4, 8, 12], [16, 20, 24]]) def test_incorrect_mul(self): data = [[7, 8, 9], [10, 11, 12]] range_ = [[1, 3], [-1, 1]] second_plot_data = PlotData(data, range_) self.assertRaises(ValueError, self.plot_data.__mul__, second_plot_data) self.assertRaises(TypeError, self.plot_data.__mul__, 'string') self.assertRaises(ValueError, self.plot_data.__rmul__, second_plot_data) self.assertRaises(TypeError, self.plot_data.__rmul__, 'string') def test_pow(self): pow_plot_data = self.plot_data**2 npt.assert_equal(pow_plot_data.data, [[1, 4, 9], [16, 25, 36]])
def set_symmetry(self, symmetrization): """Symmterizes the kmap. Args: symmetrization (str): either 'no', '2-fold', '2-fold+mirror', '3-fold', '3-fold+mirror','4-fold', '4-fold+mirror' """ data = PlotData(self.kmap['data'], self.kmap['krange']) if symmetrization == '2-fold': data.symmetrise(symmetry='2-fold', update=True) elif symmetrization == '2-fold+mirror': data.symmetrise(symmetry='2-fold', mirror=True, update=True) elif symmetrization == '3-fold': data.symmetrise(symmetry='3-fold', update=True) elif symmetrization == '3-fold+mirror': data.symmetrise(symmetry='3-fold', mirror=True, update=True) elif symmetrization == '4-fold': data.symmetrise(symmetry='4-fold', update=True) elif symmetrization == '4-fold+mirror': data.symmetrise(symmetry='4-fold', mirror=True, update=True) self.kmap['data'] = data.data self.kmap['symmetrization'] = symmetrization
def matrix_inversion(self): """Calling this method will trigger a direct fit via matrix inversion. Ax = y --> A^-1y = x Returns: (list): A list of MinimizerResults. One for each slice fitted. """ # Calculate all the orbital maps once for speed orbital_kmaps_vector = np.array([ self._cut_region(self.get_orbital_kmap(orbital.ID, self.parameters)).data for orbital in self.orbitals ]) # Filter later for non variable parameters vary_vector = [ self.parameters['w_' + str(orbital.ID)].vary for orbital in self.orbitals ] vary_vector.append(self.parameters['c'].vary) # Initial values important if orbital or background is not varied initials = [ self.parameters['w_' + str(orbital.ID)].value for orbital in self.orbitals ] initials.append(self.parameters['c'].value) weights = [] for index in self.slice_policy[1]: sliced_plot_data = self.get_sliced_kmap(index) sliced_kmap = self._cut_region(sliced_plot_data).data background = self._get_background(self.parameters) # Transform background to a equally sized map if not isinstance(background, np.ndarray): background *= np.ones(orbital_kmaps_vector[0].shape) background[np.isnan(sliced_kmap)] = 0 background = self._cut_region( PlotData(background, sliced_plot_data.range)).data aux = np.append(orbital_kmaps_vector, [background], axis=0) # All zero background would lead to singular matrix if np.all(background == 0): vary_vector[-1] = False # Subtract orbitals not to be varied from the sliced data once for i, (kmap, initial) in enumerate(zip(aux, initials)): if not vary_vector[i]: sliced_kmap -= initial * kmap N = len(aux) A = np.zeros((N, N)) y = np.zeros(N) for i in range(N): y[i] = np.nansum(sliced_kmap * aux[i]) for j in range(N): A[i, j] = np.nansum(aux[i] * aux[j]) result = np.array(initials) try: result[vary_vector] = np.linalg.solve( A[np.ix_(vary_vector, vary_vector)], y[vary_vector]) except np.linalg.LinAlgError as err: if 'Singular matrix' in str(err): result = np.zeros(y.shape) print( 'WARNING: Slice {index} produced a singular matrix.\nPlease make sure the background is non zero and there aren\'t identical orbitals loaded.' ) else: raise if N == len(orbital_kmaps_vector): # == No background result = np.append(result, 0) weights.append([index, result]) return self._construct_minimizer_result(weights)