def _get_metadata(cls, file, file_path): first_line, second_line = file.split('\n')[:2] name = os.path.splitext(os.path.split(file_path)[1])[0] keys = {config.get_key('cube', 'line_one'): first_line.strip(), config.get_key('cube', 'line_two'): second_line.strip()} return name, keys
def export_to_txt(self): if not self.interpolation.interpolation_checkbox.isChecked(): # Otherwise maps at different energies would be of different size print('Only interpolated OrbitalData can be exported.') return path = config.get_key('paths', 'txt_export_start') if path == 'None': file_name, _ = QFileDialog.getSaveFileName( None, 'Save .itx File (*.itx)') else: start_path = str(__directory__ / path) file_name, _ = QFileDialog.getSaveFileName( None, 'Save .itx File (*.itx)', str(start_path)) if not file_name: return export_energies = eval(config.get_key('orbital', 'export_energies')) if isinstance(export_energies, dict): export_energies = np.linspace(export_energies['min'], export_energies['max'], export_energies['num'], endpoint=True) kmaps = [] old_energy = self.cube_options.energy_spinbox.value() for energy in export_energies: self.cube_options.energy_spinbox.setValue(energy) kmaps.append(self.get_displayed_plot_data().data) self.cube_options.energy_spinbox.setValue(old_energy) kmaps = np.array(kmaps) xrange, yrange = self.get_displayed_plot_data().range shape = kmaps[0].shape xscale = (xrange[1] - xrange[0]) / shape[1] yscale = (yrange[1] - yrange[0]) / shape[0] name = Path(file_name).stem with open(file_name, 'w') as f: f.write('IGOR\n') f.write( f'WAVES/N=({shape[1]},{shape[0]},{len(export_energies)})\t{name}\n' ) f.write('BEGIN\n') for data in kmaps: f.write('\t') np.savetxt(f, data.T, newline='\t') f.write('\nEND\n') f.write(f'X SetScale/P x {xrange[0]},{xscale}, "A^-1", {name}; ') f.write(f'SetScale/P y {yrange[0]},{yscale}, "A^-1", {name}; ') f.write( f'SetScale/P z {export_energies[0]},{export_energies[1]-export_energies[0]}, "eV", {name}; ' ) f.write(f'SetScale d 0,0, "", {name}\n')
def plot(self, data, title, crosshair, region, phi_sample=720, line_sample=500, normalized=False): index = len(self.plot_item.listDataItems()) colors = config.get_key('profile_plot', 'colors') color = colors.split(',')[index % len(colors)] line_width = int(config.get_key('profile_plot', 'line_width')) symbols = config.get_key('profile_plot', 'symbols') symbol = symbols.split(',')[index % len(symbols)] symbol_size = int(config.get_key('profile_plot', 'symbol_size')) if isinstance(data, PlotData): x, y = self.model.get_plot_data(data, crosshair, region, phi_sample, line_sample) else: data, axis = data x = np.array(data.axes[axis].axis) y = [] for i in range(len(x)): slice_ = data.slice_from_index(i, axis=axis) plot_data = crosshair.cut_from_data(slice_, region=region).data if np.isnan(plot_data).all(): y.append(np.nan) else: if config.get_key('crosshair', 'normalized_intensity') == 'True': y.append(normalize(plot_data)) else: y.append(np.nansum(plot_data)) y = np.array(y) x = x[~np.isnan(y)] y = y[~np.isnan(y)] if normalized: y = y / max(y) self.plot_item.plot(x, y, name=title + self.title_suffixes[region], pen=mkPen(color, width=line_width), symbol=symbol, symbolPen=mkPen(color, width=symbol_size), symbolBrush=mkBrush(color))
def _set_misc(self): x = int(config.get_key('app', 'x')) y = int(config.get_key('app', 'y')) w = int(config.get_key('app', 'w')) h = int(config.get_key('app', 'h')) self.setGeometry(x, y, h, w) if config.get_key('app', 'fullscreen') == 'True': self.showMaximized() self.setWindowTitle('kMap.py') self.setWindowIcon( QIcon(str(__directory__ / 'resources/images/icon.png'))) self.show()
def export_to_hdf5(self): if not self.interpolation.interpolation_checkbox.isChecked(): print('Only interpolated OrbitalData can be exported.') return path = config.get_key('paths', 'hdf5_export_start') if path == 'None': file_name, _ = QFileDialog.getSaveFileName( None, 'Save .hdf5 File (*.hdf5)') else: start_path = str(__directory__ / path) file_name, _ = QFileDialog.getSaveFileName( None, 'Save .hdf5 File (*.hdf5)', str(start_path)) if not file_name: return else: h5file = h5py.File(file_name, 'w') export_energies = eval(config.get_key('orbital', 'export_energies')) if isinstance(export_energies, dict): export_energies = np.linspace(export_energies['min'], export_energies['max'], export_energies['num'], endpoint=True) kmaps = [] old_energy = self.cube_options.energy_spinbox.value() for energy in export_energies: self.cube_options.energy_spinbox.setValue(energy) kmaps.append(self.get_displayed_plot_data().data) self.cube_options.energy_spinbox.setValue(old_energy) kmaps = np.array(kmaps) xrange, yrange = self.get_displayed_plot_data().range h5file.create_dataset('name', data='Orbitals') h5file.create_dataset('axis_1_label', data='E_kin') h5file.create_dataset('axis_2_label', data='kx') h5file.create_dataset('axis_3_label', data='ky') h5file.create_dataset('axis_1_units', data='eV') h5file.create_dataset('axis_2_units', data='1/Å') h5file.create_dataset('axis_3_units', data='1/Å') h5file.create_dataset('axis_1_range', data=[export_energies[0], export_energies[-1]]) h5file.create_dataset('axis_2_range', data=xrange) h5file.create_dataset('axis_3_range', data=yrange) h5file.create_dataset('data', data=kmaps, dtype='f8', compression='gzip', compression_opts=9) h5file.close()
def __init__(self, data, ID, name='', meta_data={}, file_format='cube'): self.dk3D = float(config.get_key('orbital', 'dk3D')) AbstractData.__init__(self, ID, name, meta_data) Orbital.__init__(self, data, file_format=file_format, dk3D=self.dk3D, value='abs2', orbital_name=name)
def get_LUT(self): colormap = self.getHistogramWidget().gradient.colorMap() nPts = int(config.get_key('pyqtgraph', 'nPts')) LUT = colormap.getLookupTable(mode='float', alpha=True, nPts=nPts) return LUT
def load_cube_files_locally(self): # Load one or more new cube files extensions = 'cube files (*.cube);; All Files (*)' path = config.get_key('paths', 'cube_start') if path == 'None': paths, _ = QFileDialog.getOpenFileNames(None, 'Open file(s)', filter=extensions) else: start_path = str(__directory__ / path) paths, _ = QFileDialog.getOpenFileNames(None, 'Open file(s)', str(start_path), extensions) if not paths: # No file chosen logging.getLogger('kmap').info('No file chosen') return # Get Tab to load to tab = self.tab_widget.get_orbital_tab_to_load_to() # Load Data to Tab for path in paths: tab.add_orbital_from_filepath(path)
def update_label(self): plot_data = self.plot_item.get_plot_data() if plot_data == None: intensity = np.nan area = np.nan elif np.isnan(plot_data.data).all(): intensity = np.nan area = np.nan else: cut = self.model.cut_from_data(plot_data, region='center') area = plot_data.data[~np.isnan(plot_data.data )].size * plot_data.step_size[ 0] * plot_data.step_size[1] intensity = np.nansum(cut.data) decimals = int(config.get_key('crosshair', 'decimal_places')) self.point_value_label.setText(f'{intensity:.{decimals}e}') self.total_area_value.setText(f'{area:.{decimals}e}') x = self.model.x y = self.model.y self.distance_value_label.setText('%.2f' % np.sqrt(x**2 + y**2))
def fit(self): """Calling this method will trigger a lmfit with the current settings. Returns: (list): A list of MinimizerResults. One for each slice fitted. """ lmfit_padding = float(config.get_key('lmfit', 'padding')) for parameter in self.parameters.values(): if parameter.vary and parameter.value <= parameter.min: padded_value = parameter.min + lmfit_padding print('WARNING: Initial value for parameter \'%s\' had to be corrected to %f (was %f)' % ( parameter.name, padded_value, parameter.value)) parameter.value = padded_value results = [] for index in self.slice_policy[1]: slice_ = self.get_sliced_kmap(index) result = minimize(self._chi2, copy.deepcopy(self.parameters), kws={'slice_': slice_}, nan_policy='omit', method=self.method[0], xtol=self.method[1]) results.append([index, result]) return results
def load_hdf5_files(self): # Load one or more new hdf5 files log = logging.getLogger('kmap') log.info('Loading .hdf5 file(s)...') extensions = 'hdf5 files (*.hdf5 *.h5);; All Files (*)' path = config.get_key('paths', 'hdf5_start') if path == 'None': paths, _ = QFileDialog.getOpenFileNames(None, 'Open file(s)', filter=extensions) else: start_path = str(__directory__ / path) paths, _ = QFileDialog.getOpenFileNames(None, 'Open file(s)', str(start_path), extensions) if not paths: # No file chosen log.info('No file chosen') return for path in paths: self.tab_widget.open_sliced_data_tab(path)
def export_to_hdf5(self): path = config.get_key('paths', 'hdf5_export_start') if path == 'None': file_name, _ = QFileDialog.getSaveFileName( None, 'Save .hdf5 File (*.hdf5)') else: start_path = str(__directory__ / path) file_name, _ = QFileDialog.getSaveFileName( None, 'Save .hdf5 File (*.hdf5)', str(start_path)) if not file_name: return else: h5file = h5py.File(file_name, 'w') kmaps = self.get_residual_kmaps() slice_axis = self.slider.data.axes[0] x_axis = self.slider.data.axes[1] y_axis = self.slider.data.axes[2] h5file.create_dataset('name', data='Residual') h5file.create_dataset('axis_1_label', data=slice_axis.label) h5file.create_dataset('axis_2_label', data=x_axis.label) h5file.create_dataset('axis_3_label', data=y_axis.label) h5file.create_dataset('axis_1_units', data=slice_axis.units) h5file.create_dataset('axis_2_units', data=x_axis.units) h5file.create_dataset('axis_3_units', data=y_axis.units) h5file.create_dataset('axis_1_range', data=slice_axis.range) h5file.create_dataset('axis_2_range', data=x_axis.range) h5file.create_dataset('axis_3_range', data=y_axis.range) h5file.create_dataset('data', data=kmaps, dtype='f8', compression='gzip', compression_opts=9) h5file.close()
def update_label(self): plot_data = self.plot_item.get_plot_data() if plot_data == None: intensity = 0 elif np.isnan(plot_data.data).all(): intensity = np.nan else: cut = self.model.cut_from_data(plot_data, region='center') # Normalize by dividing by the number of non nan elements if config.get_key('crosshair', 'normalized_intensity') == 'True': intensity = normalize(cut.data) else: intensity = np.nansum(cut.data) if abs(intensity) > 1000: self.point_value_label.setText('%.2fk' % (intensity / 1000)) else: self.point_value_label.setText('%.2f' % intensity) x = self.model.x y = self.model.y self.distance_value_label.setText('%.2f' % np.sqrt(x**2 + y**2))
def _setup(self): s_share = config.get_key('orbital', 's_share_default') self.s_share_spinbox.setValue(float(s_share)) self.s_share_label.setVisible(False) self.s_share_spinbox.setVisible(False)
def __init__(self, mode, *args, **kwargs): super(SlicedDatabaseWindow, self).__init__(*args, **kwargs) self.setupUi(self) self._setup_tree() self._connect() # Setup database path = __directory__ / config.get_key('paths', 'database') self.database = Database(str(path)) # Open Options Window if mode == 'binding-energy': self.options = SlicedDataBaseOptions() elif mode == 'photon-energy': self.options = SlicedDataBaseOptions2() elif mode == 'cubefile': self.options = SlicedCubefileOptions() # URLs (with extra information if available) chosen self.URLs = [] self.fill_tree() self.show() self.options.show()
def set_range(self, range_): padding = float(config.get_key('pyqtgraph', 'padding')) self.view.setRange(xRange=range_[0], yRange=range_[1], update=True, padding=padding)
def plot(self, x, y, title): index = len(self.plot_item.listDataItems()) colors = config.get_key('profile_plot', 'colors') colors = colors.split(',') color = colors[index % len(colors)] line_width = int(config.get_key('profile_plot', 'line_width')) symbols = config.get_key('profile_plot', 'symbols') symbols = symbols.split(',') symbol = symbols[index % len(symbols)] symbol_size = int(config.get_key('profile_plot', 'symbol_size')) self.plot_item.plot(x, y, name=title, pen=mkPen(color, width=line_width), symbol=symbol, symbolPen=mkPen(color, width=symbol_size), symbolBrush=mkBrush(color))
def get_plot(self): image = self.plot_data.data scale = self.plot_data.step_size pixel_center = config.get_key('pyqtgraph', 'pixel_center') == 'True' pos = self._calculate_pos(scale, pixel_center=pixel_center) range_ = self._calculate_range(scale, pixel_center=pixel_center) return image, pos, scale, range_
def init_from_online(cls, url, ID, meta_data={}): log = logging.getLogger('kmap') cache_dir = Path(config.get_key('paths', 'cache')) cache_file = url.split('OrganicMolecule/')[1].replace('/', '_') cache_file = str(cache_dir / cache_file) if os.path.isfile(cache_file): log.info(f'Found file {url} in cache.') with open(cache_file, 'r') as f: file = f.read() name, keys = OrbitalData._get_metadata(file, url) name = meta_data['name'] if 'name' in meta_data else name meta_data.update(keys) file_format = 'cube' else: try: log.info(f'Loading from ID{meta_data["ID"]:05d} hdf5 file....') molecule, psi = get_remote_hdf5_orbital('143.50.77.12', '5002', int(float(meta_data['database ID'])), int(meta_data['ID'])-1) if os.path.isdir(cache_dir): log.info(f'Putting {url} into cache {cache_file}') write_cube(psi, molecule, cache_file) file = h5py.File('aux.hdf5', 'w', driver='core', backing_store=False) file.create_dataset('num_atom', data=molecule['num_atom']) file.create_dataset('chemical_numbers', data=molecule['chemical_numbers']) file.create_dataset('atomic_coordinates', data=molecule['atomic_coordinates'], dtype="float64") file.create_dataset('x', data=psi['x'], dtype="float64") file.create_dataset('y', data=psi['y'], dtype="float64") file.create_dataset('z', data=psi['z'], dtype="float64") file.create_dataset('data', data=psi['data'], dtype="float64") name = psi['name'] file_format = 'hdf5' except: log.info('HDF5 File not available, loading cube file...') log.info('Loading from database: %s' % url) with urllib.request.urlopen(url) as f: file = f.read().decode('utf-8') if os.path.isdir(cache_dir): log.info(f'Putting {url} into cache {cache_file}') with open(cache_file, 'w') as f: f.write(file) name, keys = OrbitalData._get_metadata(file, url) name = meta_data['name'] if 'name' in meta_data else name meta_data.update(keys) file_format = 'cube' return cls(file, ID, name=name, meta_data=meta_data, file_format=file_format)
def refresh_plot(self, keep_max_level=False): self.clear() if self.model.plot_data is None: return image, pos, scale, range_ = self.model.get_plot() if np.all(np.isnan(image)) == True: return old_level = self.get_levels() # Plot self.setImage(image, autoRange=True, autoLevels=True, pos=pos, scale=scale) self.set_range(range_) ratio = (range_[1][1] - range_[1][0]) / (range_[0][1] - range_[0][0]) if config.get_key('pyqtgraph', 'fixed_ratio') == 'True': self.set_aspect_ratio(ratio) else: self.set_aspect_ratio(None) if (keep_max_level or config.get_key('pyqtgraph', 'keep_max_level') == 'True'): levels = [np.nanmin(image.data), np.nanmax(image.data)] # Catch empty plots if old_level != (0, 1): levels[0] = old_level[0] if old_level[0] < levels[0] else \ levels[0] levels[1] = old_level[1] if old_level[1] > levels[1] else \ levels[1] self.set_levels(levels)
def set_default_colormap(self): default_colormap = config.get_key('colormap', 'default') try: self.set_colormap(default_colormap) except ValueError: log = logging.getLogger('kmap') log.error('The colormap set as default does not exist.') log.error(traceback.format_exc())
def get_path(self): # Path for the .json file containing the colormaps temp = __directory__ / config.get_key('paths', 'colormap') user = temp / 'colormaps_user.json' if not os.path.isfile(user): default = temp / 'colormaps_default.json' copy(default, user) return user
def set_label(self, side, label, units=None, color='k', size=1): axis = AxisItem(side, text=label, units=units, **{'color': color, 'font-size': size}) if config.get_key('pyqtgraph', 'show_axis_label') == 'True': axis.showLabel(True) else: axis.showLabel(False) self.view.setAxisItems({side: axis})
def get_orbital_kmap_by_ID(self, ID, parameters): orbital = self.ID_to_orbital(ID) if orbital is None: raise IndexError('wrong ID') weight, *parameters = parameters s_share = float(config.get_key('orbital', 's_share')) # Get scaled kmap kmap = weight * orbital.get_kmap(*parameters, s_share=s_share) return kmap
def __init__(self, plot_item): # Setup GUI super(Colormap, self).__init__() self.setupUi(self) self._connect() # Path for the .json file containing the colormaps self.path = __directory__ + config.get_key('paths', 'colormap') self.model = ColormapModel(plot_item) self.load_colormaps()
def get_orbital_kmap_by_ID(self, ID): orbital = self.ID_to_orbital(ID) if orbital is None: raise IndexError('wrong ID') parameters = self.controller.get_parameters(ID) # Split of first element weight, *other = parameters s_share = float(config.get_key('orbital', 's_share')) # Get scaled kmap kmap = weight * orbital.get_kmap(*other, s_share=s_share) return kmap
def set_labels(self, x, y): color = config.get_key('pyqtgraph', 'axis_color') size = config.get_key('pyqtgraph', 'axis_size') if isinstance(x, list): self.set_label('bottom', x[0], x[1], color, size) elif isinstance(x, Axis): self.set_label('bottom', x.label, x.units, color, size) else: self.set_label('bottom', str(x), None, color, size) if isinstance(y, list): self.set_label('left', y[0], y[1], color, size) elif isinstance(y, Axis): self.set_label('left', y.label, y.units, color, size) else: self.set_label('left', str(y), None, color, size)
def init_from_file(cls, path, ID): log = logging.getLogger('kmap') possible_paths = [path] file_name = Path(path).name possible_paths.append(Path(config.get_key('paths', 'cube_start')) / file_name) for path in config.get_key('paths', 'path').split(','): possible_paths.append(Path(path) / file_name) for path in possible_paths: log.info(f'Looking for {file_name} in {path}.') if os.path.isfile(path): log.info(f'Found.') with open(path, 'r') as f: file = f.read() name, keys = OrbitalData._get_metadata(file, path) return cls(file, ID, name=name, meta_data=keys) else: continue print(f'ERROR: File {file_name} wasn\'t found. Please add its location to the search path (general_settings.paths.path')
def _setup(self): temp = __directory__ / config.get_key('paths', 'equations') default = temp / 'background_equations_default' user = temp / 'background_equations_user' self.path = user if os.path.isfile(user) else default with open(self.path, 'r') as file: equations = file.read().split('\n') for equation in equations: self.background_combobox.addItem(equation) self.background_combobox.setCurrentIndex(0)
def update_label(self): plot_data = self.plot_item.get_plot_data() super().update_label() if plot_data == None: intensity = np.nan area = np.nan else: cut = self.model.cut_from_data(plot_data, region='ring') area = cut.data[~np.isnan(cut.data)].size * plot_data.step_size[ 0] * plot_data.step_size[1] intensity = np.nansum(cut.data) # Normalize by dividing by area if config.get_key('crosshair', 'normalized_intensity') == 'True': intensity /= area decimals = int(config.get_key('crosshair', 'decimal_places')) self.ring_value_label.setText(f'{intensity:.{decimals}e}') self.ann_area_value.setText(f'{area:.{decimals}e}')