Source code for polo.windows.pptx_dialog


from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication
from polo.designer.UI_pptx_designer import Ui_PptxDialog
from polo.utils.io_utils import *
from polo.utils.dialog_utils import *
from polo import IMAGE_CLASSIFICATIONS, DEFAULT_IMAGE_PATH, make_default_logger
from polo.widgets.run_tree import RunTree
from pathlib import Path

logger = make_default_logger(__name__)

[docs]class PptxDesignerDialog(QtWidgets.QDialog): def __init__(self, runs, parent=None): super(PptxDesignerDialog, self).__init__(parent) self.runs = runs self.ui = Ui_PptxDialog() self.ui.setupUi(self) self.setup_run_tree() self._image_class_checkboxes = self._set_up_image_classification_checkboxes() self.ui.lineEdit_3.editingFinished.connect(self._validate_typed_path) self.ui.pushButton_2.clicked.connect(self._write_presentation) self.ui.pushButton.clicked.connect(self._browse_and_update_line_edit)
[docs] def _set_up_image_classification_checkboxes(self): '''Private method that sets up the labels for the image classifications :class:`QCheckBox` instances. Should be called in the `__init__` function before displaying the dialog to the user. :return: Dictionary of image classifications which map to the :class:`QCheckBox` that corresponds to that image classification :rtype: dict ''' boxes = [self.ui.checkBox, self.ui.checkBox_2, self.ui.checkBox_3, self.ui.checkBox_4] for box, clss in zip(boxes, IMAGE_CLASSIFICATIONS): box.setText(clss) return dict(zip(IMAGE_CLASSIFICATIONS, boxes))
[docs] def _validate_typed_path(self): '''Private method that validates that a filepath in the filepath :class:`QLineEdit` widget is actually a valid path that a pptx file could be saved there. :return: True if the path is valid, otherwise returns None and shows a message box to the user. :rtype: True or None ''' path = self.ui.lineEdit_3.text() if RunSerializer().path_validator(path, parent=True): return True else: make_message_box(parent=self, message='{} is not a valid path'.format(path)).exec_() self.ui.lineEdit_3.clear()
@property def human(self): '''State of the human classifier :class:`QCheckBox`. :return: State of the :class:`QCheckBox` :rtype: bool ''' return self.ui.radioButton.isChecked() @property def marco(self): '''State of the MARCO classifier :class:`QCheckBox`. :return: State of the :class:`QCheckBox` :rtype: bool ''' return self.ui.radioButton_2.isChecked() @property def favorite(self): '''State of the favorite button. Returns boolean based on check status. Returns: bool: State of the favorite button ''' return self.ui.checkBox_5.isChecked() @property def title(self): '''Title the user has entered for the presentation via the title :class:`QLineEdit` widget. If no string has been entered will return the empty string. :return: The presentation title :rtype: str ''' return self.ui.lineEdit.text() @property def subtitle(self): '''Subtitle the user has entered for the presentation via the subtitle :class:`QLineEdit` widget. If no string has been entered will return the empty string. :return: The presentation subtitle :rtype: str ''' return self.ui.lineEdit_2.text() @property def all_dates(self): '''The state of the "Include all Dates" :class:`QCheckBox`. If it is checked this indicates that a time resolved slide should be included in the presentation. :return: State of the :class:`QCheckBox` :rtype: bool ''' return self.ui.checkBox_9.isChecked() @property def all_specs(self): '''The state of the "Include all Spectrums" :class:`QCheckBox`. If it is checked this indicates that a multi-spectrum slide should be included in the presentation. :return: State of the :class:`QCheckBox` :rtype: bool ''' return self.ui.checkBox_8.isChecked()
[docs] def setup_run_tree(self): self.ui.runTreeWidget.auto_link = False for run_name, run in self.runs.items(): self.ui.runTreeWidget.add_run_to_tree(run)
[docs] def _browse_and_update_line_edit(self): '''Private method that calls :meth:`~polo.windows.pptx_dialog.PptxDialog._get_save_path` to open a file browser. If the user selects a save path using the file browser then displays this path in the filepath :class:`QLineEdit` widget. ''' file_path = self._get_save_path() if file_path: self.ui.lineEdit_3.setText(file_path)
[docs] def set_default_titles(self): pass
# need to access the currently selected item and determine if it is a # sample or not and act on that
[docs] def _get_save_path(self): '''Private method that opens a file browser and returns the selected save filepath. :return: Filepath if one is specified by the user, empty string otherwise :rtype: str ''' file_name = QtWidgets.QFileDialog.getSaveFileName( self, 'Presentation Path') if file_name and len(file_name) >= 1: return file_name[0] else: return ''
[docs] def _parse_image_classifications(self): '''Private method to get all currently selected image classifications by reading the state of all image classification :class:`QCheckBox` instances. :return: Set of all selected image classifications :rtype: set ''' # return image classifications whose checkboxes are checked return set([clss for clss, box in self._image_class_checkboxes.items() if box.isChecked()])
[docs] def _parse_manual_image_entry(self, num_wells): '''Private method to return the image (well) numbers if they have been manually specified by the user. ''' text = self.ui.plainTextEdit.toPlainText() if text: # only parse if user has entered text text = text.split(',') for i, _ in enumerate(text): text[i] = text[i].strip().replace(',', '') # strip and remove extra commas try: text[i] = int(text[i]) - 1 # convert to base 0 assert num_wells > text[i] and text[i] >= 0 except Exception as e: if isinstance(e, AssertionError): message = 'Make sure not to enter well numbers greater than the total number of wells in the run ({})'.format(num_wells) else: message = 'Could not parse text entered. Please make sure to separate well numbers using commas and do not enter non-well-number values.' make_message_box(message).exec_() return e return text
[docs] def _get_images_from_manual_entry(self, run): indices = self._parse_manual_image_entry(len(run.images)) if isinstance(indices, Exception): return indices if indices: return [run.images[i] for i in indices]
[docs] def _get_images_from_auto_entry(self, run): return run.image_filter_query( self._parse_image_classifications(), self.human, self.marco, self.favorite )
[docs] def _write_presentation(self, run=None): '''Private method that actually does the work of generating a presentation from a :class:`Run` or :class:`HWIRun` instance. :param run: Run to create a presentation from, defaults to None :type run: Run or HWIRun, optional :return: Path to the pptx presentation is write is successful, Exception otherwise. :rtype: str or Exception ''' try: if not issubclass(type(run), Run): if self.ui.runTreeWidget.selected_run: run = self.ui.runTreeWidget.selected_run else: make_message_box('Please select a run').exec_() QApplication.restoreOverrideCursor() return # user has not entered an export path if not self.ui.lineEdit_3.text(): make_message_box( 'Please set a path to export presentation to.').exec_() QApplication.restoreOverrideCursor() return else: file_path = str(Path(self.ui.lineEdit_3.text())) images = self._get_images_from_manual_entry(run) if isinstance(images, Exception): # user attempted to enter manual # exception indicates user did something incorrectly or we # just failed to parse. None type would indicate user did # not use manual entry make_message_box( 'Could not read manual values, using auto.').exec_() images = self._get_images_from_auto_entry(run) if not images: images = self._get_images_from_auto_entry(run) if len(images) == 1 and images[0].path != DEFAULT_IMAGE_PATH or not images: # check to make sure not empty image default make_message_box( 'No images in this run fit your selection criteria.').exec_() QApplication.restoreOverrideCursor() return writer = PptxWriter(file_path) self.setEnabled(False) # disable dialog while writing QApplication.setOverrideCursor(Qt.WaitCursor) write_result = writer.make_presentation( run=run, images=images, title=self.title, subtitle=self.subtitle, all_specs=self.all_specs, all_dates=self.all_dates, ) if write_result == True: message = 'Wrote presentation to {}'.format(file_path) else: message = 'Error writing presentation {}'.format(write_result) self.setEnabled(True) QApplication.restoreOverrideCursor() make_message_box(parent=self, message=message).exec_() return write_result except Exception as e: QApplication.restoreOverrideCursor() logger.error('Caught {} at {}'.format(e, self._write_presentation)) make_message_box( parent=self, message='Failed to write presentation {}'.format(e) ).exec_() self.setEnabled(True)
[docs] def check_for_warnings(self): pass