Source code for seggridexplore

# Author: Carsten Sachse 29-Aug-2011
# Copyright: EMBL (2010 - 2018), Forschungszentrum Juelich (2019 - 2021)
# License: see license.txt for details
"""
Program to interactively explore grid searches according to different criteria
"""
from functools import partial
import os
import shutil
from spring.csinfrastr.csdatabase import SpringDataBase, GridRefineTable, GridTable, grid_base
from spring.csinfrastr.csfeatures import Features
from spring.csinfrastr.csgui import QTabWidgetCloseable
from spring.csinfrastr.cslogger import Logger
from spring.csinfrastr.csproductivity import ExtLauncher
from spring.csinfrastr.csreadinput import OptHandler
from spring.segment3d.segclassreconstruct import SegClassReconstruct
from spring.springgui.springdataexplore import SpringDataExplore, SpringDataExploreTablePane, SpringDataExploreDraw, \
    SpringDataExplore3d, SpringCommon
import sys

from EMAN2 import EMData
from PyQt5.QtCore import Qt
##from PyQt5.QtCore import pyqtSignal as SIGNAL
from PyQt5.QtWidgets import QApplication, QWidget, QStackedWidget, QPushButton, QComboBox, QSplitter, QTableWidget, \
    QFileDialog, QGridLayout
from sqlalchemy.sql.expression import desc, asc

import numpy as np


[docs]class SegGridExplorePar(object): """ Class to initiate default dictionary with input parameters including help and range values and status dictionary """ def __init__(self): # package/program identity self.package = 'emspring' self.progname = 'seggridexplore' self.proginfo = __doc__ self.code_files = [self.progname] self.seggridexplore_features = Features() self.feature_set = self.seggridexplore_features.setup(self) self.define_parameters_and_their_properties() self.define_program_states()
[docs] def define_parameters_and_their_properties(self): self.feature_set = self.seggridexplore_features.set_grid_database(self.feature_set, singular=False) self.feature_set = self.set_subgrid_merge_option(self.feature_set) self.feature_set = self.set_reconstitute_grid(self.feature_set) self.feature_set = self.seggridexplore_features.set_interactive_vs_batch_mode(self.feature_set) self.feature_set = self.set_file_prefix_symmetry_grid(self.feature_set) self.feature_set = self.set_parameter_pair_to_be_extracted(self.feature_set)
[docs] def define_program_states(self): self.feature_set.program_states['extract_desired_em_files']='Extract desired EM files' self.program_states['launch_seggridexplore_gui']='Explore different grid combinations interactively'
[docs] def set_file_prefix_symmetry_grid(self, feature_set): inp9 = 'EM name' feature_set.parameters[inp9]='recvol.hdf' feature_set.properties[inp9]=feature_set.file_properties(1,['hdf'],'saveFile') feature_set.hints[inp9]='Template output name for associated EM files from grid search: accepted image file ' +\ 'formats ({0})'.format(', '.join(feature_set.properties[inp9].ext)) feature_set.level[inp9]='beginner' feature_set.relatives[inp9]='Batch mode' return feature_set
[docs] def set_parameter_pair_to_be_extracted(self, feature_set): inp9 = 'Parameter pair' feature_set.parameters[inp9]=((1.408, 22.03)) feature_set.properties[inp9] = feature_set.Range(-1000, 1000, 0.001) feature_set.hints[inp9]='Parameter pair to extract associated EM files.' feature_set.relatives[inp9]=(('Batch mode', 'Batch mode')) feature_set.level[inp9]='intermediate' return feature_set
[docs] def set_subgrid_merge_option(self, feature_set): inp8 = 'Subgrid merge option' feature_set.parameters[inp8] = False feature_set.hints[inp8] = 'Merge subgrids from multiple grid searches. Either these subgrids were ' + \ 'generated using the subgrid option in segrefine3drid or they originate from adjacent grids with the ' + \ 'same grid spacing. Enter subgrids using wildcards * or ?? can be used to specify multiple input files.' feature_set.level[inp8]='expert' return feature_set
[docs] def set_reconstitute_grid(self, feature_set): inp1 = 'Reconstitute Grid' feature_set.parameters[inp1]=bool(True) feature_set.hints[inp1]='In case subgrids are merged reconstitute entire grid by reproducing directory tree ' + \ 'in one place and generate symbolic links to associated original files.' feature_set.relatives[inp1]='Subgrid merge option' feature_set.level[inp1]='expert' return feature_set
[docs]class SegGridExplorePreparation(object): def __init__(self, parset = None): self.log = Logger() if parset is not None: self.feature_set = parset p = self.feature_set.parameters self.grid_database = p['Grid database'] self.infile = self.grid_database self.outfile = p['EM name'] self.batch_mode = p['Batch mode'] self.parameter_pair = p['Parameter pair'] self.reconstitute_grid = p['Reconstitute Grid'] self.subgrid_merge = p['Subgrid merge option'] if self.subgrid_merge: self.subgrid_files = Features().convert_list_of_files_from_entry_string(self.grid_database)
[docs]class SegGridExploreSupport(object):
[docs] def convert_None2nan(self, x): """ Converts None objects to nan, for use in NumPy arrays. Returns an array. >>> from spring.segment3d.seggridexplore import SegGridExploreSupport >>> SegGridExploreSupport().convert_None2nan(5*[None]) [nan, nan, nan, nan, nan] """ newlist = [] for i in x: if i is not None: newlist.append(i) else: newlist.append(np.nan) return newlist
[docs] def get_general_grid_parameters(self, grid_file): grid_session = SpringDataBase().setup_sqlite_db(grid_base, grid_file) grid_combinations = grid_session.query(GridRefineTable).order_by(asc(GridRefineTable.id)).all() grid_parameters = grid_session.query(GridTable).filter(GridTable.id == grid_combinations[0].grid_id).first() return grid_session, grid_combinations, grid_parameters
[docs] def get_rises_and_rotations_and_entered_symmetry_grid(self, grid_combinations): rise_or_pitches = np.array([each_grid_combination.primary_value for each_grid_combination in grid_combinations]) rotation_or_unit_numbers = np.array([each_grid_combination.secondary_value for each_grid_combination in \ grid_combinations]) entered_symmetry_grid = SegClassReconstruct().convert_rise_rotation_or_pitch_unitnumber_series_to_grid_of_tuples\ (np.unique(rise_or_pitches), np.unique(rotation_or_unit_numbers)) return rise_or_pitches, rotation_or_unit_numbers, entered_symmetry_grid
[docs] def get_all_attr_from_search_result(self, all_grid_combinations, db_attr, filtered_attr, grid_data, zlabels, table): list_of_val = [getattr(each_grid_combination, db_attr) for each_grid_combination in \ all_grid_combinations] if set(list_of_val) != set([None]): conv_values = self.convert_None2nan(list_of_val) grid_data.append(conv_values) zlabels += SpringDataBase().get_labels_from_table(table, db_attr) filtered_attr += [db_attr] return grid_data, zlabels, filtered_attr
[docs] def get_common_criterias(self): return ['fsc_0143', 'fsc_05', 'xshift_error', 'inplane_error', 'outofplane_error', 'mean_peak', 'amp_corr_quarter_nyquist', 'amp_corr_half_nyquist', 'amp_corr_3quarter_nyquist', 'amp_correlation', 'helical_ccc_error', 'mean_helical_ccc', 'out_of_plane_dev', 'variance', 'asym_unit_count', 'avg_azimuth_sampling', 'dev_azimuth_sampling']
[docs] def get_criterias(self): additional_criteria = ['phase_residual', 'diff_noise_ccc', 'diff_noise_amp_ccc', 'cross_correlation', 'diff_noise_pr','excluded_inplane_ratio', 'excluded_out_of_plane_ratio', 'excluded_total_ratio', 'noise_ccc', 'noise_amp_ccc', 'noise_pr', 'precision', 'recall', 'f1_measure', 'f05_measure'] combined_criteria = self.get_common_criterias() + additional_criteria return combined_criteria
[docs] def get_grid_information_from_database(self, grid_file): grid_session, grid_combinations, grid_parameters = self.get_general_grid_parameters(grid_file) rise_or_pitches, rotation_or_unit_numbers, grid_pairs = \ self.get_rises_and_rotations_and_entered_symmetry_grid(grid_combinations) grid_data = [] zlabels = [] filtered_attr = [] for each_attr in self.get_criterias(): grid_data, zlabels, filtered_attr = self.get_all_attr_from_search_result(grid_combinations, each_attr, filtered_attr, grid_data, zlabels, GridRefineTable) if len(grid_data[0]) < (grid_pairs.shape[0] * grid_pairs.shape[1]): msg = 'The provided grid.db contains less data than expected from the grid parameters. ' + \ 'Double-check whether all grid runs finished successfully.' raise ValueError(msg) grid_data = [np.array(each_grid).reshape((grid_pairs.shape)) for each_grid in grid_data] files = [each_grid_combination.em_files_2d for each_grid_combination in grid_combinations] files_2d = [files for each_grid_data in grid_data] files = [each_grid_combination.em_files_3d for each_grid_combination in grid_combinations] files_3d = [files for each_grid_data in grid_data] last_grid = grid_session.query(GridTable).order_by(desc(GridTable.id)).first() xlabels = [last_grid.primary_variable for each_grid_data in grid_data] ylabels = [last_grid.secondary_variable for each_grid_data in grid_data] zxy_labels = list(zip(zlabels, xlabels, ylabels)) grid_pairs = [grid_pairs for each_grid in grid_data] hints = SpringDataBase().get_hints_from_grid_table(filtered_attr) return grid_data, grid_pairs, zxy_labels, files_2d, files_3d, hints
[docs]class SegGridExploreGuiPane(QWidget): def __init__(self, grid, grid_pairs, zxy_labels, files_2d, files_3d, parent = None): QWidget.__init__(self, parent) self.tabWidget = QTabWidgetCloseable() self.grid = grid self.grid_pairs = grid_pairs self.zxy_labels = zxy_labels self.files_2d = files_2d self.files_3d = files_3d self.layout = QGridLayout() if self.grid.shape[0] == 1 or self.grid.shape[-1] == 1: self.add_1d_plot(((0, 0)), self.zxy_labels[1]) else: self.setup_matrix_image_plot() self.table_matrix = self.prepare_table_matrix_from_symmetry_grid_pairs(self.grid, self.grid_pairs) self.table_pane = SpringDataExploreTablePane(self.table_matrix, ['GridID'] + list(self.zxy_labels)) self.table_pane.data_table.primary_id_signal.connect(partial(self.launch_external_viewer_from_index)) self.table_pane.data_table.setSelectionBehavior(QTableWidget.SelectRows) self.table_pane.data_table.setToolTip('Open connected data point by clicking on beginning of row.') self.splitter = QSplitter(Qt.Horizontal) self.splitter.addWidget(self.table_pane) self.splitter.addWidget(self.tabWidget) self.layout.addWidget(self.splitter, 0, 0, 2, 5) self.setLayout(self.layout) self.external_launcher = ExtLauncher()
[docs] def setup_matrix_image_plot(self): self.seggridexplore2d_tab = SpringDataExplore() self.seggridexplore2d_tab.on_draw(np.array(self.grid), self.grid_pairs, self.zxy_labels, '2d') self.seggridexplore2d_tab.picked_left_point.connect(partial(self.launch_external_viewers_from_index_pair)) self.seggridexplore2d_tab.picked_middle_point.connect(partial(self.add_additional_1d_tab)) self.seggridexplore2d_tab.main_frame.setToolTip('Left mouse button to open associated reprojections and ' + \ 'power spectrum (and reconstruction if provided).\nMiddle mouse button to open 1D profile of associated ' + \ '{rise_pitch} and {rot_number}.'.format(rise_pitch=self.zxy_labels[1], rot_number=self.zxy_labels[2])) self.tabWidget.addTab(self.seggridexplore2d_tab, '2D grid') self.button3d = QPushButton() self.button3d.setText('Explore3d') ##self.connect(self.button3d, SIGNAL('clicked()'), self.add_3d_surface_tab) self.button3d.clicked.connect(self.add_3d_surface_tab) self.pull_down3d = QComboBox() self.pull_down3d.addItems(['Vispy (fast)', 'Matplotlib (slow)']) self.pull_down3d.setToolTip('Choose between fast PyOpenGL (Vispy) display with less navigation options ' + \ 'for large data grids or \nslow display with many navigation options for small data grids (matplotlib)') self.layout.addWidget(self.pull_down3d, 2, 3, 1, 1) self.layout.addWidget(self.button3d, 2, 4, 1, 1)
[docs] def get_corresponding_symmetry_pair_from_picked_indices(self, index_pair): x_index, y_index = index_pair symmetry_pair = self.grid_pairs[int(y_index)][int(x_index)] return symmetry_pair, x_index, y_index
[docs] def add_1d_plot(self, index_pair, symmetry_pair): self.seggridexplore1d_tab = SpringDataExplore() self.seggridexplore1d_tab.on_draw(self.grid, self.grid_pairs, self.zxy_labels, '1d', index_pair) self.tabWidget.addTab(self.seggridexplore1d_tab, '1D: ' + \ '{0}'.format(symmetry_pair.__str__().strip(')').strip('('))) self.tabWidget.setCurrentIndex(self.tabWidget.indexOf(self.seggridexplore1d_tab)) self.seggridexplore1d_tab.picked_left_point.connect(partial(self.launch_external_viewers_from1d)) self.seggridexplore1d_tab.picked_label.connect(partial(self.define_labels_for_1d_profile)) self.seggridexplore1d_tab.index_2d.connect(partial(self.define_2d_index_for_1d_profile))
[docs] def add_additional_1d_tab(self, index_pair): symmetry_pair, x_index, y_index = self.get_corresponding_symmetry_pair_from_picked_indices(index_pair) self.add_1d_plot(index_pair, symmetry_pair)
[docs] def add_3d_surface_tab(self): if str(str(self.pull_down3d.currentText())) == 'Vispy (fast)': self.seggridexplore3d_tab = SpringDataExplore3d() self.seggridexplore3d_tab.canvas.set_data(self.grid, self.grid_pairs, self.zxy_labels) self.tabWidget.addTab(self.seggridexplore3d_tab, '3D surface (vp)') elif str(str(self.pull_down3d.currentText())) == 'Matplotlib (slow)': self.seggridexplore3d_tab = SpringDataExplore() self.seggridexplore3d_tab.on_draw(self.grid, self.grid_pairs, self.zxy_labels, '3d') self.tabWidget.addTab(self.seggridexplore3d_tab, '3D surface (mpl)') self.tabWidget.setCurrentIndex(self.tabWidget.indexOf(self.seggridexplore3d_tab))
[docs] def define_labels_for_1d_profile(self, label): self.label = label
[docs] def define_2d_index_for_1d_profile(self, index_pair): self.index_2dpair = index_pair
[docs] def launch_external_viewers_from1d(self, picked_pair_from1d): helical_rises, helical_rotations = \ SpringDataExploreDraw().extract_rise_rotation_from_symmetry_grid(self.grid_pairs) if self.label == self.zxy_labels[1]: previous_rotation_index = self.index_2dpair[0] adjusted_rise = picked_pair_from1d[0] matched_indices = np.where(np.array(helical_rises) == adjusted_rise) y_index = matched_indices[0][0] x_index = int(previous_rotation_index) elif self.label == self.zxy_labels[2]: previous_rise_index = self.index_2dpair[1] adjusted_rotation = picked_pair_from1d[0] matched_indices = np.where(np.array(helical_rotations) == adjusted_rotation) y_index = int(previous_rise_index) x_index = matched_indices[0][0] stack_index = self.get_stack_index_from_rise_and_rotation_index(x_index, y_index) self.launch_external_viewers(stack_index)
[docs] def launch_external_viewers(self, index): if self.files_2d[index] is not None: img = EMData() if not hasattr(self, 'opened'): self.opened = [] else: [os.remove(each_opened) for each_opened in self.opened] self.opened = [] for (each_file, stack_id) in self.files_2d[index]: if each_file.endswith('hdf'): print(each_file, stack_id) img.read_image(each_file, stack_id) file_name = '{0}_{1:05}{2}'.format(os.path.splitext(each_file)[0], stack_id, os.path.splitext(each_file)[1]) img.write_image(file_name) self.external_launcher.qlaunch_open_file(os.path.abspath(file_name)) self.opened.append(file_name) else: self.external_launcher.qlaunch_open_file(each_file) if self.files_3d[index] is not None: self.external_launcher.qlaunch_open_file(self.files_3d[index][0])
[docs] def launch_external_viewer_from_index(self, stack_index): self.launch_external_viewers(stack_index)
[docs] def launch_external_viewers_from_index_pair(self, index_pair): x_index, y_index = index_pair stack_index = self.get_stack_index_from_rise_and_rotation_index(x_index, y_index) self.launch_external_viewers(stack_index)
[docs] def get_stack_index_from_rise_and_rotation_index(self, x_index, y_index): x_count, y_count = self.grid_pairs.shape stack_index = int(x_index + y_count * y_index) return stack_index
[docs] def exitApp(self): self.close()
[docs] def prepare_table_matrix_from_symmetry_grid_pairs(self, symmetry_grid_np, symmetry_grid_pairs): sym_id = np.arange(symmetry_grid_np.size) symmetry_grid_cc_seq = symmetry_grid_np.ravel() rises_seq, rotation_seq = list(zip(*symmetry_grid_pairs.ravel())) table_matrix = np.vstack([sym_id, symmetry_grid_cc_seq, rises_seq, rotation_seq]) return table_matrix
[docs]class SegGridExploreGui(SegGridExploreSupport, QWidget): def __init__(self, feature_set, parent = None): QWidget.__init__(self, parent) self.feature_set = feature_set self.properties = feature_set.properties # self.grid_database = self.feature_set.parameters['Grid database'] self.grid_database = 'grid.db' self = SpringCommon().setup_spring_page_top(self, feature_set) self.grids, self.grid_pairs, self.zxy_labels, self.files_2d, self.files_3d, hints = \ self.get_grid_information_from_database(self.grid_database) self.stackedPane = QStackedWidget() self.currentPaneIndex = 0 self.panes = [] for pane_id, each_grid in enumerate(self.grids): self.pane = SegGridExploreGuiPane(self.grids[pane_id], self.grid_pairs[pane_id], self.zxy_labels[pane_id], self.files_2d[pane_id], self.files_3d[pane_id]) self.stackedPane.addWidget(self.pane) self.panes.append(self.pane) self.layout.addWidget(self.stackedPane, 1, 0, 2, 5) self.stackedPane.setCurrentIndex(self.currentPaneIndex) self.z_labels = [each_label[0] for each_label in self.zxy_labels ] self.pull_down_panes = QComboBox() self.pull_down_panes.addItems(self.z_labels) self.pull_down_panes.setToolTip(hints) ##self.connect(self.pull_down_panes, SIGNAL('currentIndexChanged(int)'), self.update_panes) self.pull_down_panes.currentIndexChanged.connect(self.update_panes) self.layout.addWidget(self.pull_down_panes, 0, 3, 1, 1) self.pull_down_pairs = QComboBox() self.items = [] for each_grid in self.grid_pairs: self.items.append([ 'Grid ID:{0}: {1}'.format(each_grid_id, str(each_pair).strip(')').strip('(')) for \ each_grid_id, each_pair in enumerate(each_grid.ravel())]) self.pull_down_pairs.addItems(self.items[self.currentPaneIndex]) self.layout.addWidget(self.pull_down_pairs, 3, 3, 1, 1) self.save_button = QPushButton() self.save_button.setText('Save') self.save_button.setToolTip('Save associated EM files.') self.save_button.setShortcut('Ctrl+S') ##self.connect(self.save_button, SIGNAL('clicked()'), self.saveEmFile) self.save_button.clicked.connect(self.saveEmFile) self.layout.addWidget(self.save_button, 3, 4, 1, 1) self.setLayout(self.layout)
[docs] def update_panes(self, value): self.currentPaneIndex = value self.stackedPane.setCurrentIndex(self.currentPaneIndex)
[docs] def saveEmFile(self): fname, _filter = QFileDialog.getSaveFileName(self , 'Save EM file', '.', 'Files ({0})'.\ format('*.' + ' *.'.join(list(self.properties.values())[1].ext))) fname = str(fname) index = self.pull_down_pairs.currentIndex() files = self.files_2d[self.currentPaneIndex][index] img = EMData() for each_file_id, (each_file_name, each_stack_id) in enumerate(files): img.read_image(each_file_name, each_stack_id) img.write_image(os.path.splitext(fname)[0] + '2d' + os.path.splitext(fname)[-1], each_file_id) volume_name = self.files_3d[self.currentPaneIndex][index][0] if volume_name is not None: img.read_image(volume_name) img.write_image(os.path.splitext(fname)[0] + '3d' + os.path.splitext(fname)[-1])
[docs]class SegGridExploreMerge(SegGridExplorePreparation):
[docs] def perform_simple_additive_merge(self, sorted_subgrid_files): merged_session = SpringDataBase().setup_sqlite_db(grid_base, 'grid.db') for each_subgrid_id, each_subgrid_file in enumerate(sorted_subgrid_files): each_grid = SpringDataBase().setup_sqlite_db(grid_base, each_subgrid_file) if each_subgrid_id == 0: merged_session = SpringDataBase().copy_all_table_data_from_one_session_to_another_session(GridTable, merged_session, each_grid, merge_ids=True) merged_session = SpringDataBase().copy_all_table_data_from_one_session_to_another_session(GridRefineTable, merged_session, each_grid, merge_ids=True) merged_session.commit() return merged_session
[docs] def check_whether_seamless_grid_merging_is_possible(self, primary_min, primary_max, primary_inc): """ >>> from spring.segment3d.seggridexplore import SegGridExplore >>> s = SegGridExplore() >>> s.check_whether_seamless_grid_merging_is_possible([16.25, 16.36], [16.35, 16.45], [0.01]) >>> s.check_whether_seamless_grid_merging_is_possible([16.25, 16.38], [16.35, 16.45], [0.01]) Traceback (most recent call last): File '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/doctest.py', line 1254, in __run compileflags, 1) in test.globs File '<doctest spring.segment3d.seggridexplore.SegGridExploreMerge.check_whether_seamless_grid_merging_is_possible[3]>', line 1, in <module> s.check_whether_seamless_grid_merging_is_possible([16.25, 16.38], [16.35, 16.45], [0.01]) File '/Users/sachse/Documents/en_casa/EMBL/08_python/26_springbox/develop-eggs/spring-dev/spring/segment3d/seggridexplore.py', line 517, in check_whether_seamless_grid_merging_is_possible raise ValueError(msg) ValueError: You have specified grid datbases to be merged that can not be merged seamlessly without gaps into a continuous grid. """ primary_min = [abs(each_min) for each_min in list(primary_min)] primary_max = [abs(each_max) for each_max in list(primary_max)] primary_inc = [abs(each_inc) for each_inc in list(primary_inc)] primary_min.sort() primary_max.sort() for each_ext_id, each_max in enumerate(primary_max[:-1]): next_min = primary_min[each_ext_id + 1] computed_next_min = each_max + primary_inc[0] if abs(computed_next_min - next_min) > primary_inc[0]/100.0: msg = 'You have specified grid datbases to be merged that can not be merged seamlessly without ' + \ 'gaps into a continuous grid.' raise ValueError(msg)
[docs] def update_new_grid_min_and_max_after_merge(self, primary_min, primary_max, second_min, second_max, merged_session): grid = merged_session.query(GridTable).first() grid.primary_min = min(primary_min) grid.primary_max = max(primary_max) grid.second_min = min(second_min) grid.second_max = max(second_max) merged_session.merge(grid) merged_session.commit() return merged_session
[docs] def merge_grids_from_files(self, sorted_subgrid_files, primary_min, primary_max, second_min, second_max, primary_inc, second_inc, same_increments): same_max_and_mins = len(primary_min) + len(primary_max) + len(second_min) + len(second_max) if same_max_and_mins == 4 and same_increments == 2: merged_session = self.perform_simple_additive_merge(sorted_subgrid_files) if not same_max_and_mins == 4 and same_increments == 2: if 0 in second_inc or 0 in primary_inc: pass else: self.check_whether_seamless_grid_merging_is_possible(primary_min, primary_max, primary_inc) self.check_whether_seamless_grid_merging_is_possible(second_min, second_max, second_inc) merged_session = self.perform_simple_additive_merge(sorted_subgrid_files) merged_session = self.update_new_grid_min_and_max_after_merge(primary_min, primary_max, second_min, second_max, merged_session) os.rename('grid.db', 'grid_not_sorted.db') tmp_session = SpringDataBase().setup_sqlite_db(grid_base, 'grid_not_sorted.db') grid = tmp_session.query(GridRefineTable).\ order_by(GridRefineTable.primary_value.asc()).\ order_by(GridRefineTable.secondary_value.asc()).all() shutil.copy('grid_not_sorted.db', 'grid.db') merged_session = SpringDataBase().setup_sqlite_db(grid_base, 'grid.db') columns = SpringDataBase().get_columns_from_table(GridRefineTable) for each_grid_id, each_grid_point in enumerate(grid): data = SpringDataBase().get_data_from_entry(columns, each_grid_point) data['id'] = each_grid_id + 1 merged_session.merge(GridRefineTable(**data)) merged_session.commit() os.remove('grid_not_sorted.db') return merged_session
[docs] def merge_subgrids_into_single_grid_file(self, subgrid_files): split_files = [os.path.split(each_file)[-1] for each_file in subgrid_files] sorted_subgrid_files = [subgrid_files[each_ind] for each_ind in np.argsort(split_files)] file_grid_parameters = [] for each_subgrid_file in sorted_subgrid_files: each_grid = SpringDataBase().setup_sqlite_db(grid_base, each_subgrid_file) grid_entries = each_grid.query(GridTable).first() file_grid_parameters.append(grid_entries) primary_var = set([each_file_grid.primary_variable for each_file_grid in file_grid_parameters]) secondary_var = set([each_file_grid.secondary_variable for each_file_grid in file_grid_parameters]) primary_min = set([each_file_grid.primary_min for each_file_grid in file_grid_parameters]) primary_max = set([each_file_grid.primary_max for each_file_grid in file_grid_parameters]) second_min = set([each_file_grid.second_min for each_file_grid in file_grid_parameters]) second_max = set([each_file_grid.second_max for each_file_grid in file_grid_parameters]) primary_inc = set([each_file_grid.primary_inc for each_file_grid in file_grid_parameters]) second_inc = set([each_file_grid.second_inc for each_file_grid in file_grid_parameters]) same_variables = len(primary_var) + len(secondary_var) same_increments = len(primary_inc) + len(second_inc) for each_inc in list(primary_inc) + list(second_inc): if each_inc == 0: same_variables = 2 same_increments = 2 entities = [] if not same_variables == 2: entities.append('variables') if not same_increments == 2: entities.append('increments') if not same_variables == 2 or not same_increments == 2: msg = '' for each_entity in entities: msg += 'You have specified grid databases to be merged that do not match in their primary or ' + \ 'secondary {0}. This way they cannot be merged. Double-check the specified files. '.format(each_entity) raise ValueError(msg) merged_session = self.merge_grids_from_files(sorted_subgrid_files, primary_min, primary_max, second_min, second_max, primary_inc, second_inc, same_increments) return merged_session
[docs]class SegGridExplore(SegGridExploreMerge):
[docs] def launch_seggridexplore_gui(self, feature_set): self.log.fcttolog() app = QApplication(sys.argv) gridexplor = SegGridExploreGui(feature_set) gridexplor.show() app.exec_()
[docs] def extract_desired_em_files(self): self.log.fcttolog() grids, grid_pairs, zxy_labels, files_2d, files_3d, hints = \ SegGridExploreSupport().get_grid_information_from_database(self.grid_database) vol = EMData() for each_index, each_grid_pair in enumerate(grid_pairs[0].ravel()): if each_grid_pair == self.parameter_pair: vol.read_image(files_3d[0][each_index][0]) outfile = '{0}{1:04}{2}'.format(os.path.splitext(self.outfile)[0], each_index, os.path.splitext(self.outfile)[-1]) vol.write_image(outfile) self.log.plog(90 * (each_index + 1) / len(grid_pairs[0].ravel()) + 10)
[docs] def launch_seggridexplore(self): if self.subgrid_merge: grid_session = self.merge_subgrids_into_single_grid_file(self.subgrid_files) if self.reconstitute_grid: self.write_symbolic_links_to_have_merged_data_in_one_place(grid_session) else: shutil.copy(self.grid_database, 'grid.db') self.log.plog(10) if not self.batch_mode: self.launch_seggridexplore_gui(self.feature_set) else: self.extract_desired_em_files() self.log.endlog(self.feature_set)
[docs]def main(): # Option handling parset = SegGridExplorePar() mergeparset = OptHandler(parset) ######## Program sseg = SegGridExplore(mergeparset) sseg.launch_seggridexplore()
if __name__ == '__main__': main()