Пример #1
0
    def init_gui(self):

        vbox = QtWidgets.QVBoxLayout()
        hbox = QtWidgets.QHBoxLayout()
        inner_layout = QtWidgets.QVBoxLayout()
        button_hbox = QtWidgets.QHBoxLayout()
        res_hbox = QtWidgets.QHBoxLayout()

        self.res_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
        self.res_slider.setMinimum(0)
        self.res_slider.setMaximum(
            (self.RES_MAX - self.RES_MIN) / self.RES_INTERVAL)
        # self.res_slider.setTickInterval(1)
        # self.res_slider.setTickPosition(QtWidgets.QSlider.TicksBelow)
        self.res_slider.valueChanged[int].connect(self.slider_changing)
        self.res_slider.sliderReleased.connect(self.slider_released)

        self.lineedit = QtWidgets.QLineEdit(self)
        self.lineedit.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.lineedit.setMinimumSize(30, 1)
        self.lineedit.setMaximumSize(40, 40)
        self.lineedit.returnPressed.connect(self.lineedit_return)

        res_hbox.addWidget(QtWidgets.QLabel('resolution:', self))
        res_hbox.addWidget(self.res_slider)
        res_hbox.addWidget(self.lineedit)

        # set font
        #        font = QFont("Courier New", 14)
        #        table_view.setFont(font)
        # set column width to fit contents (set font first!)
        # enable sortingq
        #        table_view.setSortingEnabled(True)

        ok_button = QtWidgets.QPushButton('Ok', self)
        ok_button.setAutoDefault(False)
        ok_button.clicked.connect(self.ok)

        cancel_button = QtWidgets.QPushButton('Cancel', self)
        cancel_button.setAutoDefault(False)
        cancel_button.clicked.connect(self.cancel)

        button_hbox.addStretch()
        button_hbox.addWidget(ok_button)
        button_hbox.addStretch()
        button_hbox.addWidget(cancel_button)
        button_hbox.addStretch()

        self.table_view = CalculationTable(self)
        self.res_slider.setValue(
            (self.resolution - self.RES_MIN) / self.RES_INTERVAL)
        self.update_table()

        self.surf_check = QtWidgets.QCheckBox(
            'calculate surface based cavities', self)
        self.surf_check.setChecked(True)
        self.center_check = QtWidgets.QCheckBox(
            'calculate center based cavities', self)
        self.gyration_tensor_check = QtWidgets.QCheckBox(
            'calculate gyration tensor parameters', self)
        self.gyration_tensor_check.setToolTip(
            'squared_gyration_radius, asphericity, acylindricity, anisotropy')
        self.overwrite_check = QtWidgets.QCheckBox(
            'overwrite existing results', self)
        self.exporthdf5_check = QtWidgets.QCheckBox(
            'export results as HDF5 files', self)
        self.exporttext_check = QtWidgets.QCheckBox(
            'export results as text files', self)
        self.exportdir_radio_input = QtWidgets.QRadioButton(
            'export to the directory of the input files', self)
        self.exportdir_radio_config = QtWidgets.QRadioButton(
            'export to %s' % config.Path.result_dir, self)

        self.exportdir_radio_input.setChecked(True)

        covalence_radii_by_element = self.__get_all_covalence_radii_by_element(
        )
        self.radii_widget = RadiiWidget(covalence_radii_by_element,
                                        self.file_frame_dict, self)

        inner_layout.addLayout(res_hbox)
        inner_layout.addWidget(self.table_view)
        inner_layout.addWidget(self.surf_check)
        inner_layout.addWidget(self.center_check)
        inner_layout.addWidget(self.gyration_tensor_check)
        inner_layout.addWidget(self.overwrite_check)
        inner_layout.addWidget(self.exporthdf5_check)
        inner_layout.addWidget(self.exporttext_check)
        inner_layout.addWidget(self.exportdir_radio_input)
        inner_layout.addWidget(self.exportdir_radio_config)

        hbox.addLayout(inner_layout)
        hbox.addWidget(self.radii_widget)

        vbox.addLayout(hbox)
        vbox.addLayout(button_hbox)

        self.setLayout(vbox)
Пример #2
0
    def init_gui(self):

        vbox            = QtWidgets.QVBoxLayout()
        hbox            = QtWidgets.QHBoxLayout()
        inner_layout    = QtWidgets.QVBoxLayout()
        button_hbox     = QtWidgets.QHBoxLayout()
        res_hbox        = QtWidgets.QHBoxLayout()

        self.res_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
        self.res_slider.setMinimum(0)
        self.res_slider.setMaximum((self.RES_MAX - self.RES_MIN) / self.RES_INTERVAL)
        # self.res_slider.setTickInterval(1)
        # self.res_slider.setTickPosition(QtWidgets.QSlider.TicksBelow)
        self.res_slider.valueChanged[int].connect(self.slider_changing)
        self.res_slider.sliderReleased.connect(self.slider_released)

        self.lineedit   = QtWidgets.QLineEdit(self)
        self.lineedit.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.lineedit.setMinimumSize(30, 1)
        self.lineedit.setMaximumSize(40, 40)
        self.lineedit.returnPressed.connect(self.lineedit_return)

        res_hbox.addWidget(QtWidgets.QLabel('resolution:', self))
        res_hbox.addWidget(self.res_slider)
        res_hbox.addWidget(self.lineedit)

        # set font
#        font = QFont("Courier New", 14)
#        table_view.setFont(font)
        # set column width to fit contents (set font first!)
        # enable sortingq
#        table_view.setSortingEnabled(True)

        ok_button = QtWidgets.QPushButton('Ok', self)
        ok_button.setAutoDefault(False)
        ok_button.clicked.connect(self.ok)

        cancel_button = QtWidgets.QPushButton('Cancel', self)
        cancel_button.setAutoDefault(False)
        cancel_button.clicked.connect(self.cancel)

        button_hbox.addStretch()
        button_hbox.addWidget(ok_button)
        button_hbox.addStretch()
        button_hbox.addWidget(cancel_button)
        button_hbox.addStretch()

        self.table_view = CalculationTable(self)
        self.res_slider.setValue((self.resolution-self.RES_MIN)/self.RES_INTERVAL)
        self.update_table()

        self.surf_check = QtWidgets.QCheckBox('calculate surface based cavities', self)
        self.surf_check.setChecked(True)
        self.center_check = QtWidgets.QCheckBox('calculate center based cavities', self)
        self.gyration_tensor_check = QtWidgets.QCheckBox('calculate gyration tensor parameters', self)
        self.gyration_tensor_check.setToolTip('squared_gyration_radius, asphericity, acylindricity, anisotropy')
        self.overwrite_check = QtWidgets.QCheckBox('overwrite existing results', self)
        self.exporthdf5_check = QtWidgets.QCheckBox('export results as HDF5 files', self)
        self.exporttext_check = QtWidgets.QCheckBox('export results as text files', self)
        self.exportdir_radio_input = QtWidgets.QRadioButton('export to the directory of the input files', self)
        self.exportdir_radio_config = QtWidgets.QRadioButton('export to %s' % config.Path.result_dir, self)

        self.exportdir_radio_input.setChecked(True)

        covalence_radii_by_element = self.__get_all_covalence_radii_by_element()
        self.radii_widget = RadiiWidget(covalence_radii_by_element, self.file_frame_dict, self)

        inner_layout.addLayout(res_hbox)
        inner_layout.addWidget(self.table_view)
        inner_layout.addWidget(self.surf_check)
        inner_layout.addWidget(self.center_check)
        inner_layout.addWidget(self.gyration_tensor_check)
        inner_layout.addWidget(self.overwrite_check)
        inner_layout.addWidget(self.exporthdf5_check)
        inner_layout.addWidget(self.exporttext_check)
        inner_layout.addWidget(self.exportdir_radio_input)
        inner_layout.addWidget(self.exportdir_radio_config)

        hbox.addLayout(inner_layout)
        hbox.addWidget(self.radii_widget)

        vbox.addLayout(hbox)
        vbox.addLayout(button_hbox)

        self.setLayout(vbox)
Пример #3
0
class CalculationSettingsDialog(QtWidgets.QDialog):

    RES_MIN = 32
    RES_MAX = 1024
    RES_INTERVAL = 32

    def __init__(self, parent, file_frame_dict):
        QtWidgets.QDialog.__init__(self, parent)

        self.control = parent.control
        self.resolution = config.Computation.std_resolution
        self.filenames = file_frame_dict.keys()
        self.file_frame_dict = file_frame_dict

        self.init_gui()
        self.setWindowTitle("Calculation Settings")

    def init_gui(self):

        vbox = QtWidgets.QVBoxLayout()
        hbox = QtWidgets.QHBoxLayout()
        inner_layout = QtWidgets.QVBoxLayout()
        button_hbox = QtWidgets.QHBoxLayout()
        res_hbox = QtWidgets.QHBoxLayout()

        self.res_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
        self.res_slider.setMinimum(0)
        self.res_slider.setMaximum(
            (self.RES_MAX - self.RES_MIN) / self.RES_INTERVAL)
        # self.res_slider.setTickInterval(1)
        # self.res_slider.setTickPosition(QtWidgets.QSlider.TicksBelow)
        self.res_slider.valueChanged[int].connect(self.slider_changing)
        self.res_slider.sliderReleased.connect(self.slider_released)

        self.lineedit = QtWidgets.QLineEdit(self)
        self.lineedit.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.lineedit.setMinimumSize(30, 1)
        self.lineedit.setMaximumSize(40, 40)
        self.lineedit.returnPressed.connect(self.lineedit_return)

        res_hbox.addWidget(QtWidgets.QLabel('resolution:', self))
        res_hbox.addWidget(self.res_slider)
        res_hbox.addWidget(self.lineedit)

        # set font
        #        font = QFont("Courier New", 14)
        #        table_view.setFont(font)
        # set column width to fit contents (set font first!)
        # enable sortingq
        #        table_view.setSortingEnabled(True)

        ok_button = QtWidgets.QPushButton('Ok', self)
        ok_button.setAutoDefault(False)
        ok_button.clicked.connect(self.ok)

        cancel_button = QtWidgets.QPushButton('Cancel', self)
        cancel_button.setAutoDefault(False)
        cancel_button.clicked.connect(self.cancel)

        button_hbox.addStretch()
        button_hbox.addWidget(ok_button)
        button_hbox.addStretch()
        button_hbox.addWidget(cancel_button)
        button_hbox.addStretch()

        self.table_view = CalculationTable(self)
        self.res_slider.setValue(
            (self.resolution - self.RES_MIN) / self.RES_INTERVAL)
        self.update_table()

        self.surf_check = QtWidgets.QCheckBox(
            'calculate surface based cavities', self)
        self.surf_check.setChecked(True)
        self.center_check = QtWidgets.QCheckBox(
            'calculate center based cavities', self)
        self.gyration_tensor_check = QtWidgets.QCheckBox(
            'calculate gyration tensor parameters', self)
        self.gyration_tensor_check.setToolTip(
            'squared_gyration_radius, asphericity, acylindricity, anisotropy')
        self.overwrite_check = QtWidgets.QCheckBox(
            'overwrite existing results', self)
        self.exporthdf5_check = QtWidgets.QCheckBox(
            'export results as HDF5 files', self)
        self.exporttext_check = QtWidgets.QCheckBox(
            'export results as text files', self)
        self.exportdir_radio_input = QtWidgets.QRadioButton(
            'export to the directory of the input files', self)
        self.exportdir_radio_config = QtWidgets.QRadioButton(
            'export to %s' % config.Path.result_dir, self)

        self.exportdir_radio_input.setChecked(True)

        covalence_radii_by_element = self.__get_all_covalence_radii_by_element(
        )
        self.radii_widget = RadiiWidget(covalence_radii_by_element,
                                        self.file_frame_dict, self)

        inner_layout.addLayout(res_hbox)
        inner_layout.addWidget(self.table_view)
        inner_layout.addWidget(self.surf_check)
        inner_layout.addWidget(self.center_check)
        inner_layout.addWidget(self.gyration_tensor_check)
        inner_layout.addWidget(self.overwrite_check)
        inner_layout.addWidget(self.exporthdf5_check)
        inner_layout.addWidget(self.exporttext_check)
        inner_layout.addWidget(self.exportdir_radio_input)
        inner_layout.addWidget(self.exportdir_radio_config)

        hbox.addLayout(inner_layout)
        hbox.addWidget(self.radii_widget)

        vbox.addLayout(hbox)
        vbox.addLayout(button_hbox)

        self.setLayout(vbox)

    def __get_all_covalence_radii_by_element(self):
        covalence_radii_by_element, elements_by_frame, element_combinations = self.__read_atom_info(
        )
        return covalence_radii_by_element

    def __get_elements_by_frame(self):
        covalence_radii_by_element, elements_by_frame, element_combinations = self.__read_atom_info(
        )
        return elements_by_frame

    def __get_element_combinations(self):
        covalence_radii_by_element, elements_by_frame, element_combinations = self.__read_atom_info(
        )
        return element_combinations

    def __read_atom_info(self):
        method = self.__read_atom_info.__func__
        for attr in ('covalence_radii_by_element', 'elements_by_frame',
                     'element_combinations'):
            if not hasattr(method, attr):
                setattr(method, attr, None)

        if (method.covalence_radii_by_element is None
                or method.elements_by_frame is None
                or method.element_combinations is None):
            radii = {}
            elements_by_frame = {}
            element_combinations = set()
            for filepath, frames in self.file_frame_dict.iteritems():
                elements_by_frame[filepath] = {}
                inputfile = file.File.open(filepath)
                if frames == (-1, ):
                    frames = range(inputfile.info.num_frames)
                for frame in frames:
                    atoms = inputfile.getatoms(frame)
                    current_radii = atoms.covalence_radii_by_element
                    current_elements = atoms.elements
                    radii.update(current_radii)
                    elements_by_frame[filepath][frame] = current_elements
                    element_combinations.add(tuple(current_elements))
            method.covalence_radii_by_element = radii
            method.elements_by_frame = elements_by_frame
        return (method.covalence_radii_by_element, method.elements_by_frame,
                method.element_combinations)

    def __update_cutoff_history(self):
        timestamp = datetime.datetime.now()
        user_cutoff_radii = self.radii_widget.cutoff_radii
        elements = self.__get_all_covalence_radii_by_element().keys()
        if not isinstance(user_cutoff_radii, collections.Iterable):
            user_cutoff_radii = dict(
                (elem, user_cutoff_radii) for elem in elements)
        elements_by_frame = self.__get_elements_by_frame()
        new_history = []
        for filepath, frames in self.file_frame_dict.iteritems():
            filename = os.path.basename(filepath)
            file_elements = elements_by_frame[filepath]
            for frame in frames:
                elements = file_elements[frame]
                frame_cutoff_radii = dict(
                    (elem, user_cutoff_radii[elem]) for elem in elements)
                history_entry = HistoryEntry(filename, frame, timestamp,
                                             frame_cutoff_radii)
                new_history.append(history_entry)
        cutoff_history.extend(new_history)
        cutoff_history.save()

    def __update_cutoff_presets(self):
        save_preset_name = self.radii_widget.save_preset_name
        if save_preset_name is not None:
            user_cutoff_radii = self.radii_widget.cutoff_radii
            cutoff_presets.add(Preset(save_preset_name, user_cutoff_radii))
            cutoff_presets.save()

    def update_table(self):
        # get timestamps for selected frames for each file

        # surface based
        surface_ts = []
        center_ts = []
        for i, ts in enumerate(self.timestamps(center_based=False)):
            frames = (range(file.File.open(self.filenames[i]).info.num_frames)
                      if self.file_frame_dict[self.filenames[i]][0] == -1 else
                      self.file_frame_dict[self.filenames[i]])
            surface_ts.append([])
            for frame in frames:
                surface_ts[i].append(ts[frame])

        # center based timestamps for the given frames
        center_ts = []
        for i, ts in enumerate(self.timestamps(center_based=True)):
            frames = (range(file.File.open(self.filenames[i]).info.num_frames) \
                      if self.file_frame_dict[self.filenames[i]][0] == -1 \
                      else self.file_frame_dict[self.filenames[i]])
            center_ts.append([])
            for frame in frames:
                center_ts[i].append(ts[frame])

        # reduce to a single value per file
        surface_ts = ["X" if "X" in ts else ts[0] for ts in surface_ts]
        center_ts = ["X" if "X" in ts else ts[0] for ts in center_ts]
        basenames = [os.path.basename(path) for path in self.filenames]
        frames = [
            str([frame + 1 for frame in self.file_frame_dict[f]])[1:-1]
            if not self.file_frame_dict[f][0] == -1 else 'all'
            for f in self.filenames
        ]

        data_list = zip(basenames, surface_ts, center_ts, frames)

        # set table data
        header = ['dataset', 'surface based', 'center based', 'frames']
        table_model = TableModel(self, data_list, header)
        self.table_view.setModel(table_model)
        self.table_view.resizeColumnsToContents()

        # calculate table size to set its minimum size
        width = (self.table_view.model().columnCount(self.table_view) -
                 1) + self.table_view.verticalHeader().width()
        for i in range(self.table_view.model().columnCount(self.table_view)):
            width += self.table_view.columnWidth(i)
        self.table_view.setMinimumWidth(width)

        height = (self.table_view.model().rowCount(self.table_view) -
                  1) + self.table_view.horizontalHeader().height()
        for i in range(self.table_view.model().rowCount(self.table_view)):
            height += self.table_view.rowHeight(i)
        self.table_view.setMinimumHeight(height)

    def lineedit_return(self):
        try:
            self.resolution = int(self.lineedit.text())
            value = (self.resolution - self.RES_MIN) / self.RES_INTERVAL
            self.res_slider.setValue(value)
            self.update_table()
        except ValueError:
            pass

    def slider_changing(self, value):
        self.lineedit.setText(str(value * self.RES_INTERVAL + self.RES_MIN))

    def slider_released(self):
        self.resolution = self.res_slider.value(
        ) * self.RES_INTERVAL + self.RES_MIN
        self.update_table()

    def timestamps(self, center_based=False):
        return [
            self.control.calculation.calculatedframes(
                file.get_abspath(fn), self.resolution, not center_based,
                center_based).prettystrings() for fn in self.filenames
        ]

    def ok(self):
        self.lineedit_return()
        self.__update_cutoff_history()
        self.__update_cutoff_presets()
        self.done(QtWidgets.QDialog.Accepted)

    def cancel(self):
        self.done(QtWidgets.QDialog.Rejected)

    def calculation_settings(self):
        calc_settings = None
        while True:
            ok = self.exec_()
            if ok != QtWidgets.QDialog.Accepted:
                break
            try:
                cutoff_radii = self.radii_widget.cutoff_radii
                surface_based = self.surf_check.isChecked()
                center_based = self.center_check.isChecked()
                gyration_tensor = self.gyration_tensor_check.isChecked()
                overwrite = self.overwrite_check.isChecked()
                exporthdf5 = self.exporthdf5_check.isChecked()
                exporttext = self.exporttext_check.isChecked()
                if self.exportdir_radio_config.isChecked():
                    exportdir = os.path.expanduser(config.Path.result_dir)
                else:
                    exportdir = None
                calc_settings = calculation.CalculationSettings(
                    datasets=self.file_frame_dict,
                    resolution=self.resolution,
                    cutoff_radii=cutoff_radii,
                    domains=True,
                    surface_cavities=surface_based,
                    center_cavities=center_based,
                    gyration_tensor=gyration_tensor,
                    recalculate=overwrite,
                    exporthdf5=exporthdf5,
                    exporttext=exporttext,
                    exportdir=exportdir)
                break
            except ValueError:
                pass

        return (calc_settings, ok)
Пример #4
0
class CalculationSettingsDialog(QtWidgets.QDialog):

    RES_MIN = 32
    RES_MAX = 1024
    RES_INTERVAL = 32

    def __init__(self, parent, file_frame_dict):
        QtWidgets.QDialog.__init__(self, parent)

        self.control = parent.control
        self.resolution = config.Computation.std_resolution
        self.filenames = file_frame_dict.keys()
        self.file_frame_dict = file_frame_dict

        self.init_gui()
        self.setWindowTitle("Calculation Settings")

    def init_gui(self):

        vbox            = QtWidgets.QVBoxLayout()
        hbox            = QtWidgets.QHBoxLayout()
        inner_layout    = QtWidgets.QVBoxLayout()
        button_hbox     = QtWidgets.QHBoxLayout()
        res_hbox        = QtWidgets.QHBoxLayout()

        self.res_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
        self.res_slider.setMinimum(0)
        self.res_slider.setMaximum((self.RES_MAX - self.RES_MIN) / self.RES_INTERVAL)
        # self.res_slider.setTickInterval(1)
        # self.res_slider.setTickPosition(QtWidgets.QSlider.TicksBelow)
        self.res_slider.valueChanged[int].connect(self.slider_changing)
        self.res_slider.sliderReleased.connect(self.slider_released)

        self.lineedit   = QtWidgets.QLineEdit(self)
        self.lineedit.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.lineedit.setMinimumSize(30, 1)
        self.lineedit.setMaximumSize(40, 40)
        self.lineedit.returnPressed.connect(self.lineedit_return)

        res_hbox.addWidget(QtWidgets.QLabel('resolution:', self))
        res_hbox.addWidget(self.res_slider)
        res_hbox.addWidget(self.lineedit)

        # set font
#        font = QFont("Courier New", 14)
#        table_view.setFont(font)
        # set column width to fit contents (set font first!)
        # enable sortingq
#        table_view.setSortingEnabled(True)

        ok_button = QtWidgets.QPushButton('Ok', self)
        ok_button.setAutoDefault(False)
        ok_button.clicked.connect(self.ok)

        cancel_button = QtWidgets.QPushButton('Cancel', self)
        cancel_button.setAutoDefault(False)
        cancel_button.clicked.connect(self.cancel)

        button_hbox.addStretch()
        button_hbox.addWidget(ok_button)
        button_hbox.addStretch()
        button_hbox.addWidget(cancel_button)
        button_hbox.addStretch()

        self.table_view = CalculationTable(self)
        self.res_slider.setValue((self.resolution-self.RES_MIN)/self.RES_INTERVAL)
        self.update_table()

        self.surf_check = QtWidgets.QCheckBox('calculate surface based cavities', self)
        self.surf_check.setChecked(True)
        self.center_check = QtWidgets.QCheckBox('calculate center based cavities', self)
        self.gyration_tensor_check = QtWidgets.QCheckBox('calculate gyration tensor parameters', self)
        self.gyration_tensor_check.setToolTip('squared_gyration_radius, asphericity, acylindricity, anisotropy')
        self.overwrite_check = QtWidgets.QCheckBox('overwrite existing results', self)
        self.exporthdf5_check = QtWidgets.QCheckBox('export results as HDF5 files', self)
        self.exporttext_check = QtWidgets.QCheckBox('export results as text files', self)
        self.exportdir_radio_input = QtWidgets.QRadioButton('export to the directory of the input files', self)
        self.exportdir_radio_config = QtWidgets.QRadioButton('export to %s' % config.Path.result_dir, self)

        self.exportdir_radio_input.setChecked(True)

        covalence_radii_by_element = self.__get_all_covalence_radii_by_element()
        self.radii_widget = RadiiWidget(covalence_radii_by_element, self.file_frame_dict, self)

        inner_layout.addLayout(res_hbox)
        inner_layout.addWidget(self.table_view)
        inner_layout.addWidget(self.surf_check)
        inner_layout.addWidget(self.center_check)
        inner_layout.addWidget(self.gyration_tensor_check)
        inner_layout.addWidget(self.overwrite_check)
        inner_layout.addWidget(self.exporthdf5_check)
        inner_layout.addWidget(self.exporttext_check)
        inner_layout.addWidget(self.exportdir_radio_input)
        inner_layout.addWidget(self.exportdir_radio_config)

        hbox.addLayout(inner_layout)
        hbox.addWidget(self.radii_widget)

        vbox.addLayout(hbox)
        vbox.addLayout(button_hbox)

        self.setLayout(vbox)

    def __get_all_covalence_radii_by_element(self):
        covalence_radii_by_element, elements_by_frame, element_combinations = self.__read_atom_info()
        return covalence_radii_by_element

    def __get_elements_by_frame(self):
        covalence_radii_by_element, elements_by_frame, element_combinations = self.__read_atom_info()
        return elements_by_frame

    def __get_element_combinations(self):
        covalence_radii_by_element, elements_by_frame, element_combinations = self.__read_atom_info()
        return element_combinations

    def __read_atom_info(self):
        method = self.__read_atom_info.__func__
        for attr in ('covalence_radii_by_element', 'elements_by_frame', 'element_combinations'):
            if not hasattr(method, attr):
                setattr(method, attr, None)

        if (method.covalence_radii_by_element is None or
            method.elements_by_frame is None or
            method.element_combinations is None):
            radii = {}
            elements_by_frame = {}
            element_combinations = set()
            for filepath, frames in self.file_frame_dict.iteritems():
                elements_by_frame[filepath] = {}
                inputfile = file.File.open(filepath)
                if frames == (-1, ):
                    frames = range(inputfile.info.num_frames)
                for frame in frames:
                    atoms = inputfile.getatoms(frame)
                    current_radii = atoms.covalence_radii_by_element
                    current_elements = atoms.elements
                    radii.update(current_radii)
                    elements_by_frame[filepath][frame] = current_elements
                    element_combinations.add(tuple(current_elements))
            method.covalence_radii_by_element = radii
            method.elements_by_frame = elements_by_frame
        return (method.covalence_radii_by_element, method.elements_by_frame, method.element_combinations)

    def __update_cutoff_history(self):
        timestamp = datetime.datetime.now()
        user_cutoff_radii = self.radii_widget.cutoff_radii
        elements = self.__get_all_covalence_radii_by_element().keys()
        if not isinstance(user_cutoff_radii, collections.Iterable):
            user_cutoff_radii = dict((elem, user_cutoff_radii) for elem in elements)
        elements_by_frame = self.__get_elements_by_frame()
        new_history = []
        for filepath, frames in self.file_frame_dict.iteritems():
            filename = os.path.basename(filepath)
            file_elements = elements_by_frame[filepath]
            for frame in frames:
                elements = file_elements[frame]
                frame_cutoff_radii = dict((elem, user_cutoff_radii[elem]) for elem in elements)
                history_entry = HistoryEntry(filename, frame, timestamp, frame_cutoff_radii)
                new_history.append(history_entry)
        cutoff_history.extend(new_history)
        cutoff_history.save()

    def __update_cutoff_presets(self):
        save_preset_name = self.radii_widget.save_preset_name
        if save_preset_name is not None:
            user_cutoff_radii = self.radii_widget.cutoff_radii
            cutoff_presets.add(Preset(save_preset_name, user_cutoff_radii))
            cutoff_presets.save()

    def update_table(self):
        # get timestamps for selected frames for each file

        # surface based
        surface_ts = []
        center_ts = []
        for i, ts in enumerate(self.timestamps(center_based=False)):
            frames = (range(file.File.open(self.filenames[i]).info.num_frames)
                      if self.file_frame_dict[self.filenames[i]][0] == -1
                      else self.file_frame_dict[self.filenames[i]])
            surface_ts.append([])
            for frame in frames:
                surface_ts[i].append(ts[frame])

        # center based timestamps for the given frames
        center_ts = []
        for i, ts in enumerate(self.timestamps(center_based=True)):
            frames = (range(file.File.open(self.filenames[i]).info.num_frames) \
                      if self.file_frame_dict[self.filenames[i]][0] == -1 \
                      else self.file_frame_dict[self.filenames[i]])
            center_ts.append([])
            for frame in frames:
                center_ts[i].append(ts[frame])

        # reduce to a single value per file
        surface_ts = ["X" if "X" in ts else ts[0] for ts in surface_ts]
        center_ts = ["X" if "X" in ts else ts[0] for ts in center_ts]
        basenames = [os.path.basename(path) for path in self.filenames]
        frames = [str([frame + 1 for frame in self.file_frame_dict[f]])[1:-1] if not self.file_frame_dict[f][0] == -1 else 'all' for f in self.filenames]

        data_list = zip(basenames, surface_ts, center_ts, frames)

        # set table data
        header = ['dataset', 'surface based', 'center based', 'frames']
        table_model = TableModel(self, data_list, header)
        self.table_view.setModel(table_model)
        self.table_view.resizeColumnsToContents()

        # calculate table size to set its minimum size
        width = (self.table_view.model().columnCount(self.table_view) - 1) + self.table_view.verticalHeader().width()
        for i in range(self.table_view.model().columnCount(self.table_view)):
            width += self.table_view.columnWidth(i)
        self.table_view.setMinimumWidth(width)

        height = (self.table_view.model().rowCount(self.table_view) - 1) + self.table_view.horizontalHeader().height()
        for i in range(self.table_view.model().rowCount(self.table_view)):
            height += self.table_view.rowHeight(i)
        self.table_view.setMinimumHeight(height)

    def lineedit_return(self):
        try:
            self.resolution = int(self.lineedit.text())
            value = (self.resolution - self.RES_MIN) / self.RES_INTERVAL
            self.res_slider.setValue(value)
            self.update_table()
        except ValueError:
            pass

    def slider_changing(self, value):
        self.lineedit.setText(str(value * self.RES_INTERVAL + self.RES_MIN))

    def slider_released(self):
        self.resolution = self.res_slider.value() * self.RES_INTERVAL + self.RES_MIN
        self.update_table()

    def timestamps(self, center_based=False):
        return [self.control.calculation.calculatedframes(
                file.get_abspath(fn),
                self.resolution,
                not center_based,
                center_based).prettystrings()
                for fn in self.filenames]

    def ok(self):
        self.lineedit_return()
        self.__update_cutoff_history()
        self.__update_cutoff_presets()
        self.done(QtWidgets.QDialog.Accepted)

    def cancel(self):
        self.done(QtWidgets.QDialog.Rejected)

    def calculation_settings(self):
        calc_settings = None
        while True:
            ok = self.exec_()
            if ok != QtWidgets.QDialog.Accepted:
                break
            try:
                cutoff_radii = self.radii_widget.cutoff_radii
                surface_based = self.surf_check.isChecked()
                center_based = self.center_check.isChecked()
                gyration_tensor = self.gyration_tensor_check.isChecked()
                overwrite = self.overwrite_check.isChecked()
                exporthdf5 = self.exporthdf5_check.isChecked()
                exporttext = self.exporttext_check.isChecked()
                if self.exportdir_radio_config.isChecked():
                    exportdir = os.path.expanduser(config.Path.result_dir)
                else:
                    exportdir = None
                calc_settings = calculation.CalculationSettings(datasets=self.file_frame_dict,
                                                                resolution=self.resolution,
                                                                cutoff_radii=cutoff_radii,
                                                                domains=True,
                                                                surface_cavities=surface_based,
                                                                center_cavities=center_based,
                                                                gyration_tensor=gyration_tensor,
                                                                recalculate=overwrite,
                                                                exporthdf5=exporthdf5,
                                                                exporttext=exporttext,
                                                                exportdir=exportdir)
                break
            except ValueError:
                pass

        return (calc_settings, ok)