Exemple #1
0
def fetch_and_run(prep_id, limit, image=False, czi=False, testing=False):

    slide_processor = SlideProcessor(prep_id, session)
    sqlController = SqlController()
    if czi:
        slide_processor.process_czi_dir()
    if image:
        manipulate_images(prep_id, limit, testing)
        sqlController.set_step_completed_in_progress_ini(
            prep_id, '1-3_setup_thumbnails')
        sqlController.set_step_completed_in_progress_ini(
            prep_id, '1-4_setup_sorted_filenames')
    #slide_processor.update_tif_data()
    #slide_processor.test_tables()
    print('Finished manipulating images')
class GUISetupMain(QWidget):
    def __init__(self, stack, parent=None):
        super(GUISetupMain, self).__init__(parent)

        # Stack specific info, determined from dropdown menu selection
        self.stack = stack
        self.fileLocationManager = FileLocationManager(self.stack)
        self.sqlController = SqlController()
        self.sqlController.get_animal_info(self.stack)
        self.stain = self.sqlController.histology.counterstain
        self.curr_step = self.sqlController.get_current_step_from_progress_ini(self.stack)

        # Init UI
        self.init_ui()

        # Set buttons functionality
        self.b_1_4.clicked.connect(lambda: self.click_button(self.b_1_4))
        self.b_1_6.clicked.connect(lambda: self.click_button(self.b_1_6))
        self.b_exit.clicked.connect(lambda: self.click_button(self.b_exit))

        # Update buttons
        self.update_buttons()

        # Center the GUI
        self.center()

    def init_ui(self):
        self.grid_buttons = QGridLayout()
        self.grid_bottom = QGridLayout()

        # Grid buttons
        self.b_1_4 = QPushButton("Setup Sorted Filenames")
        self.grid_buttons.addWidget(self.b_1_4)
        self.b_1_6 = QPushButton("Run automatic setup scripts")
        self.grid_buttons.addWidget(self.b_1_6)

        # Grid bottom
        self.progress = QProgressBar(self)
        self.progress.hide()
        self.grid_bottom.addWidget(self.progress)

        self.b_exit = QPushButton("Exit")
        self.b_exit.setDefault(True)
        self.grid_bottom.addWidget(self.b_exit)

        # Super grid
        self.super_grid = QGridLayout()
        self.super_grid.addLayout(self.grid_buttons, 1, 0)
        self.super_grid.addLayout(self.grid_bottom, 2, 0)
        self.setLayout(self.super_grid)
        self.setWindowTitle("Align to Active Brainstem Atlas - Setup Page")
        self.resize(1000, 450)

    def update_buttons(self):
        """
        Locates where you are in the pipeline by reading the brains_info/STACK_progress.ini

        Buttons corresponding to previous steps are marked as "completed", buttons corresponding
        to future steps are marked as "unpressable" and are grayed out.
        """

        self.stain = self.sqlController.histology.counterstain

        try:
            self.curr_step = self.sqlController.get_current_step_from_progress_ini(self.stack)
            print('format grid buttons current step is', self.curr_step)

            curr_step_index = ['1-4', '1-5', '1-6'].index(self.curr_step[:3])
            for index, button in enumerate([self.b_1_4, self.b_1_6]):
                if index <= curr_step_index + 1:
                    button.setEnabled(True)
                else:
                    button.setEnabled(False)

        # If there are no stacks/brains that have been started
        except KeyError:
            for button in [self.b_1_4, self.b_1_6]:
                button.setEnabled(False)

    def click_button(self, button):
        """
        If any of the "grid" buttons are pressed, this is the callback function.
        In this case, "grid" buttons have a one-to_one correspondance to the steps in the pipeline.
        The completion of each step means you move onto the next one.
        """
        # Setup/Create sorted filenames
        if button == self.b_1_4:
            try:
                subprocess.call(['python', 'a_GUI_setup_sorted_filenames.py', self.stack])
                self.update_buttons()
            except Exception as e:
                sys.stderr.write(str(e))
        # Run automatic scripts
        elif button == self.b_1_6:
            message = "This operation will take a long time."
            message += " Several minutes per image."
            QMessageBox.about(self, "Popup Message", message)
            preprocess_setup(self.stack, self.stain)

            #subprocess.call(['python', 'utilities/a_script_preprocess_1.py', self.stack, self.stain])
            subprocess.call(['python', 'a_script_preprocess_2.py', self.stack, self.stain])

            self.sqlController.set_step_completed_in_progress_ini(self.stack, '1-6_setup_scripts')

            """
            pipeline_status = get_pipeline_status(self.stack)
            if not 'preprocess_1' in pipeline_status and \
                    not 'preprocess_2' in pipeline_status and not 'setup' in pipeline_status:
                self.sqlController.set_step_completed_in_progress_ini(self.stack, '1-6_setup_scripts')
                sys.exit(app.exec_())

            pipeline_status = get_pipeline_status(self.stack)
            if pipeline_status == 'a_script_preprocess_3':
                self.sqlController.set_step_completed_in_progress_ini(self.stack, '1-6_setup_scripts')
                sys.exit(app.exec_())
            # else:
            #    print '\n\n\n\n'
            #    print 'pipeline_status:'
            ##    print pipeline_status
            #    print '\n\n\n\n'
            #    #set_step_completed_in_progress_ini( self.stack, '1-6_setup_scripts')
            print('finished in button 4')
            """
        elif button == self.b_exit:
            self.closeEvent(None)

        self.update_buttons()

    def center(self):
        """
        This function simply aligns the GUI to the center of your monitor.
        """
        frameGm = self.frameGeometry()
        screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos())
        centerPoint = QApplication.desktop().screenGeometry(screen).center()
        frameGm.moveCenter(centerPoint)
        self.move(frameGm.topLeft())

    def closeEvent(self, event):
        sys.exit(app.exec_())
Exemple #3
0
class GUISortedFilenames(QWidget):
    def __init__(self, stack, parent=None):
        super(GUISortedFilenames, self).__init__(parent)

        self.stack = stack
        self.fileLocationManager = FileLocationManager(self.stack)
        self.sqlController = SqlController()
        self.sqlController.get_animal_info(self.stack)

        self.valid_sections = self.sqlController.get_valid_sections(stack)
        self.valid_section_keys = sorted(list(self.valid_sections))

        self.curr_section_index = 0
        self.curr_section = None

        self.init_ui()

        self.b_rotate_left.clicked.connect(
            lambda: self.click_button(self.b_rotate_left))
        self.b_rotate_right.clicked.connect(
            lambda: self.click_button(self.b_rotate_right))
        self.b_flip_vertical.clicked.connect(
            lambda: self.click_button(self.b_flip_vertical))
        self.b_flip_horozontal.clicked.connect(
            lambda: self.click_button(self.b_flip_horozontal))
        self.b_move_left.clicked.connect(
            lambda: self.click_button(self.b_move_left))
        self.b_move_right.clicked.connect(
            lambda: self.click_button(self.b_move_right))
        self.b_quality.currentIndexChanged.connect(
            lambda: self.click_button(self.b_quality))
        self.b_remove.clicked.connect(lambda: self.click_button(self.b_remove))
        self.b_help.clicked.connect(lambda: self.click_button(self.b_help))
        self.b_done.clicked.connect(lambda: self.click_button(self.b_done))

        self.set_curr_section(self.curr_section_index)

    def init_ui(self):
        self.font_h1 = QFont("Arial", 32)
        self.font_p1 = QFont("Arial", 16)

        self.grid_top = QGridLayout()
        self.grid_body_upper = QGridLayout()
        self.grid_body = QGridLayout()
        self.grid_body_lower = QGridLayout()

        self.resize(1600, 1100)

        # Grid Top
        self.e_title = QLineEdit()
        self.e_title.setAlignment(Qt.AlignCenter)
        self.e_title.setFont(self.font_h1)
        self.e_title.setReadOnly(True)
        self.e_title.setText("Setup Sorted Filenames")
        self.e_title.setFrame(False)
        self.grid_top.addWidget(self.e_title, 0, 0)

        self.b_help = QPushButton("HELP")
        self.b_help.setDefault(True)
        self.b_help.setEnabled(True)
        self.grid_top.addWidget(self.b_help, 0, 1)

        # Grid BODY UPPER
        self.e_filename = QLineEdit()
        self.e_filename.setAlignment(Qt.AlignCenter)
        self.e_filename.setFont(self.font_p1)
        self.e_filename.setReadOnly(True)
        self.e_filename.setText("Filename: ")
        self.grid_body_upper.addWidget(self.e_filename, 0, 2)

        self.e_section = QLineEdit()
        self.e_section.setAlignment(Qt.AlignCenter)
        self.e_section.setFont(self.font_p1)
        self.e_section.setReadOnly(True)
        self.e_section.setText("Section: ")
        self.grid_body_upper.addWidget(self.e_section, 0, 3)

        # Grid BODY
        self.viewer = ImageViewer(self)
        self.grid_body.addWidget(self.viewer, 0, 0)

        # Grid BODY LOWER
        self.b_flip_vertical = QPushButton("Flip vertically")
        self.grid_body_lower.addWidget(self.b_flip_vertical, 0, 0)

        self.b_flip_horozontal = QPushButton("Flop horizontally")
        self.grid_body_lower.addWidget(self.b_flip_horozontal, 0, 1)

        self.b_rotate_left = QPushButton("Rotate Left")
        self.grid_body_lower.addWidget(self.b_rotate_left, 0, 2)

        self.b_rotate_right = QPushButton("Rotate Right")
        self.grid_body_lower.addWidget(self.b_rotate_right, 0, 3)

        self.b_move_left = QPushButton("<--   Move Section Left   <--")
        #self.grid_body_lower.addWidget(self.b_move_left, 1, 0)

        self.b_move_right = QPushButton("-->   Move Section Right   -->")
        #self.grid_body_lower.addWidget(self.b_move_right, 1, 1)

        self.b_quality = QComboBox()
        self.b_quality.addItems([
            'Section quality: unusable', 'Section quality: blurry',
            'Section quality: good'
        ])
        #self.grid_body_lower.addWidget(self.b_quality, 1, 2)

        self.b_remove = QPushButton("Remove section")
        #self.grid_body_lower.addWidget(self.b_remove, 1, 3)

        self.progress = QProgressBar(self)
        self.grid_body_lower.addWidget(self.progress, 2, 0, 1, 3)
        self.progress.hide()

        self.b_done = QPushButton("Finished")
        self.grid_body_lower.addWidget(self.b_done, 2, 3)

        # Super grid
        self.supergrid = QGridLayout()
        self.supergrid.addLayout(self.grid_top, 0, 0)
        self.supergrid.addLayout(self.grid_body_upper, 1, 0)
        self.supergrid.addLayout(self.grid_body, 2, 0)
        self.supergrid.addLayout(self.grid_body_lower, 3, 0)

        # Set layout and window title
        self.setLayout(self.supergrid)
        self.setWindowTitle("Q")

    def set_curr_section(self, section_index=-1):
        """
        Sets the current section to the section passed in.
        Will automatically update curr_section, prev_section, and next_section.
        Updates the header fields and loads the current section image.
        """
        if section_index == -1:
            section_index = self.curr_section_index

        # Update curr, prev, and next section
        self.curr_section_index = section_index
        self.curr_section = self.valid_sections[self.valid_section_keys[
            self.curr_section_index]]

        # Update the section and filename at the top
        self.e_filename.setText(self.curr_section['destination'])
        self.e_section.setText(str(self.curr_section['section_number']))

        # Get filepath of "curr_section" and set it as viewer's photo
        img_fp = os.path.join(self.fileLocationManager.thumbnail_prep,
                              self.curr_section['destination'])
        self.viewer.set_photo(img_fp)

        # Update the quality selection in the bottom left
        index = self.b_quality.findText(self.curr_section['quality'],
                                        Qt.MatchFixedString)
        if index >= 0:
            self.b_quality.setCurrentIndex(index)

    def get_valid_section_index(self, section_index):
        if section_index >= len(self.valid_sections):
            return 0
        elif section_index < 0:
            return len(self.valid_sections) - 1
        else:
            return section_index

    def click_button(self, button):
        if button == self.b_quality:
            curr_section = self.valid_sections[self.valid_section_keys[
                self.curr_section_index]]
            curr_section['quality'] = self.b_quality.currentText()
            self.sqlController.save_valid_sections(self.valid_sections)

        elif button in [self.b_move_left, self.b_move_right, self.b_remove]:
            if button == self.b_move_left:
                self.sqlController.move_section(
                    self.stack, self.curr_section['section_number'], -1)
            elif button == self.b_move_right:
                self.sqlController.move_section(
                    self.stack, self.curr_section['section_number'], 1)
            elif button == self.b_remove:
                result = self.message_box(
                    'Are you sure you want to totally remove this section from this brain?\n\n'
                    +
                    'Warning: The image will be marked as irrelevant to the current brain!',
                    True)

                # The answer is Yes
                if result == 2:
                    # Remove the current section from "self.valid_sections
                    self.sqlController.inactivate_section(
                        self.stack, self.curr_section['section_number'])

                    self.valid_sections = self.sqlController.get_valid_sections(
                        self.stack)
                    self.valid_section_keys = sorted(list(self.valid_sections))

                    if self.curr_section_index == 0:
                        self.curr_section_index = len(
                            self.valid_section_keys) - 1
                    else:
                        self.curr_section_index = self.curr_section_index - 1
            else:
                pass

            # Update the Viewer info and displayed image
            self.valid_sections = self.sqlController.get_valid_sections(
                self.stack)
            self.valid_section_keys = sorted(list(self.valid_sections))
            self.set_curr_section(self.curr_section_index)

        elif button in [
                self.b_flip_vertical, self.b_flip_horozontal,
                self.b_rotate_right, self.b_rotate_left
        ]:
            """
            Transform_type must be "rotate", "flip", or "flop".
            These transformations get applied to all the active sections. The actual
            conversions take place on the thumbnails and the raw files.
            The transformed raw files get placed in the preps/oriented dir.
            """

            index = [
                self.b_flip_vertical, self.b_flip_horozontal,
                self.b_rotate_right, self.b_rotate_left
            ].index(button)
            op = ['flip', 'flop', 'right', 'left'][index]

            size = len(self.valid_sections.values()) - 1
            self.progress_bar(True, size)

            for index, section in enumerate(self.valid_sections.values()):
                thumbnail_path = os.path.join(
                    self.fileLocationManager.thumbnail_prep,
                    section['destination'])
                if os.path.isfile(thumbnail_path):
                    self.transform_image(thumbnail_path, op)

                self.progress.setValue(index)

            self.progress_bar(False, size)
            self.set_curr_section(section_index=-1)

        elif button == self.b_help:
            self.message_box(
                'This GUI is used to align slices to each other. The shortcut commands are as follows: \n\n'
                + '-  `[`: Go back one section. \n' +
                '-  `]`: Go forward one section. \n\n' +
                'Use the buttons on the bottom panel to move', False)

        elif button == self.b_done:
            self.message_box(
                "All selected operations will now be performed on the full sized raw images"
                +
                "This may take an hour or two, depending on how many operations are queued.",
                False)

            # Apply the transformations to the real images
            self.apply_queued_transformations()

            self.sqlController.set_step_completed_in_progress_ini(
                self.stack, '1-4_setup_sorted_filenames')
            self.sqlController.set_step_completed_in_progress_ini(
                self.stack, '1-5_setup_orientations')
            sys.exit(app.exec_())

    def transform_image(self, filename, op):
        def get_last_2d(data):
            if data.ndim <= 2:
                return data
            m, n = data.shape[-2:]
            return data.flat[:m * n].reshape(m, n)

        img = io.imread(filename)
        img = get_last_2d(img)

        # Rotating a multidimensional image has to be done backwards.
        # To rotate right, do np.rot(img, 3), to rotate left, do np.rot(img, 1)
        if op == 'left':
            img = np.rot90(img, 3)
        elif op == 'right':
            img = np.rot90(img, 1)
        elif op == 'flip':
            img = np.flipud(img)
        elif op == 'flop':
            img = np.fliplr(img)

        os.unlink(filename)
        io.imsave(filename, img)
        self.save_to_web_thumbnail(filename, img)

    def save_to_web_thumbnail(self, filename, img):
        filename = os.path.basename(filename)
        png_file = os.path.splitext(filename)[0] + '.png'
        png_path = os.path.join(self.fileLocationManager.thumbnail_web,
                                png_file)
        if os.path.exists(png_path):
            os.unlink(png_path)
        io.imsave(png_path, img)

    def apply_queued_transformations(self):
        pass

    def progress_bar(self, show, max_value):
        if show:
            self.progress.setMaximum(max_value)
            self.progress.show()
        else:
            self.progress.hide()

        self.b_quality.setDisabled(show)
        self.b_move_left.setDisabled(show)
        self.b_move_right.setDisabled(show)
        self.b_flip_vertical.setDisabled(show)
        self.b_flip_horozontal.setDisabled(show)
        self.b_rotate_right.setDisabled(show)
        self.b_rotate_left.setDisabled(show)
        self.b_remove.setDisabled(show)
        self.b_done.setDisabled(show)

    def message_box(self, text, is_warn):
        msg_box = QMessageBox()
        msg_box.setText(text)

        if is_warn:
            msg_box.addButton(QPushButton('Cancel'), QMessageBox.RejectRole)
            msg_box.addButton(QPushButton('No'), QMessageBox.NoRole)
            msg_box.addButton(QPushButton('Yes'), QMessageBox.YesRole)

        return msg_box.exec_()

    def keyPressEvent(self, event):
        try:
            key = event.key()
        except AttributeError:
            key = event

        if key == 91:  # [
            index = self.get_valid_section_index(self.curr_section_index - 1)
            self.set_curr_section(index)
        elif key == 93:  # ]
            index = self.get_valid_section_index(self.curr_section_index + 1)
            self.set_curr_section(index)
        else:
            print(key)

    def closeEvent(self, event):
        sys.exit(app.exec_())
Exemple #4
0
class init_GUI(QWidget):
    def __init__(self, stack, parent=None):
        super(init_GUI, self).__init__(parent)
        self.font_h1 = QFont("Arial", 32)
        self.font_p1 = QFont("Arial", 16)
        self.queued_transformations = []

        # create a dataManager object
        self.sqlController = SqlController()
        self.stack = stack
        self.fileLocationManager = FileLocationManager(self.stack)
        self.sqlController.get_animal_info(self.stack)

        self.valid_sections = self.sqlController.get_valid_sections(stack)
        self.valid_section_keys = sorted(list(self.valid_sections))

        section_length = len(self.valid_section_keys)

        self.curr_section_index = section_length // 2
        self.prev_section_index = self.curr_section_index
        self.next_section_index = self.curr_section_index
        self.curr_section = self.valid_sections[self.valid_section_keys[
            self.curr_section_index]]['destination']
        self.prev_section = self.getPrevValidSection(self.curr_section_index)
        self.next_section = self.getNextValidSection(self.curr_section_index)

        self.initUI()

    def initUI(self):
        # Set Layout and Geometry of Window
        self.grid_top = QGridLayout()
        self.grid_body_upper = QGridLayout()
        self.grid_body = QGridLayout()
        self.grid_body_lower = QGridLayout()
        self.grid_bottom = QGridLayout()
        self.grid_blank = QGridLayout()

        # self.setFixedSize(1600, 1000)
        self.resize(1600, 1000)

        ### VIEWER ### (Grid Body)
        self.viewer = ImageViewer(self)
        self.viewer.photoClicked.connect(self.photoClicked)

        ### Grid TOP ###
        # Static Text Field (Title)
        self.e1 = QLineEdit()
        self.e1.setValidator(QIntValidator())
        self.e1.setAlignment(Qt.AlignCenter)
        self.e1.setFont(self.font_h1)
        self.e1.setReadOnly(True)
        self.e1.setText("Orient Images")
        self.e1.setFrame(False)
        self.grid_top.addWidget(self.e1, 0, 0)
        # Button Text Field
        self.b_help = QPushButton("HELP")
        self.b_help.setDefault(True)
        self.b_help.setEnabled(True)
        self.b_help.clicked.connect(
            lambda: self.help_button_press(self.b_help))
        self.b_help.setStyleSheet(
            "color: rgb(0,0,0); background-color: rgb(250,250,250);")
        self.grid_top.addWidget(self.b_help, 0, 1)

        ### Grid BODY UPPER ###
        # Static Text Field
        self.e4 = QLineEdit()
        self.e4.setAlignment(Qt.AlignCenter)
        self.e4.setFont(self.font_p1)
        self.e4.setReadOnly(True)
        self.e4.setText("Filename: ")
        # self.e4.setStyleSheet("color: rgb(250,50,50); background-color: rgb(250,250,250);")
        self.grid_body_upper.addWidget(self.e4, 0, 2)
        # Static Text Field
        self.e5 = QLineEdit()
        self.e5.setAlignment(Qt.AlignCenter)
        self.e5.setFont(self.font_p1)
        self.e5.setReadOnly(True)
        self.e5.setText("Section: ")
        # self.e5.setStyleSheet("color: rgb(250,50,50); background-color: rgb(250,250,250);")
        self.grid_body_upper.addWidget(self.e5, 0, 3)

        ### Grid BODY ###
        # Custom VIEWER
        self.grid_body.addWidget(self.viewer, 0, 0)

        ### Grid BODY LOWER ###
        # Button Text Field
        self.b1 = QPushButton("Flip image(s) across central vertical line")
        self.b1.setDefault(True)
        self.b1.setEnabled(True)
        self.b1.clicked.connect(lambda: self.buttonPress(self.b1))
        self.b1.setStyleSheet(
            "color: rgb(0,0,0); background-color: rgb(250,250,200);")
        self.grid_body_lower.addWidget(self.b1, 0, 0)
        # Button Text Field
        self.b2 = QPushButton("Flop image(s) across central horozontal line")
        self.b2.setDefault(True)
        self.b2.setEnabled(True)
        self.b2.clicked.connect(lambda: self.buttonPress(self.b2))
        self.b2.setStyleSheet(
            "color: rgb(0,0,0); background-color: rgb(250,250,200);")
        self.grid_body_lower.addWidget(self.b2, 1, 0)
        # Button Text Field
        self.b3 = QPushButton("Rotate Image(s)")
        self.b3.setDefault(True)
        self.b3.setEnabled(True)
        self.b3.clicked.connect(lambda: self.buttonPress(self.b3))
        self.b3.setStyleSheet(
            "color: rgb(0,0,0); background-color: rgb(250,200,250);")
        self.grid_body_lower.addWidget(self.b3, 0, 1, 1, 2)
        # Checkbox
        self.cb_1 = QCheckBox("Apply transformation to ALL images")
        self.cb_1.setChecked(True)
        self.cb_1.setEnabled(False)
        self.grid_body_lower.addWidget(self.cb_1, 0, 3)
        # Static Text Field
        self.e6 = QLineEdit()
        self.e6.setMaximumWidth(250)
        self.e6.setAlignment(Qt.AlignRight)
        self.e6.setReadOnly(True)
        self.e6.setText("Degrees to rotate (clockwise!): ")
        self.grid_body_lower.addWidget(self.e6, 1, 1)
        # Dropbown Menu (ComboBox) for selecting Stack
        self.cb = QComboBox()
        self.cb.addItems(['90', '180', '270'])
        # self.cb.addItems( ['Rotate by 90 degrees', 'Rotate by 180 degrees', 'Rotate by 270 degrees'] )
        # self.cb.addItems( ['45', '90', '135', '180', '225', '270', '315'] )
        self.grid_body_lower.addWidget(self.cb, 1, 2)
        # Button Text Field
        self.b_done = QPushButton("Done orienting")
        self.b_done.setDefault(True)
        self.b_done.setEnabled(True)
        self.b_done.clicked.connect(lambda: self.buttonPress(self.b_done))
        self.b_done.setStyleSheet(
            "color: rgb(0,0,0); background-color: #dfbb19;")
        self.grid_body_lower.addWidget(self.b_done, 1, 3)

        # Grid stretching
        # self.grid_body_upper.setColumnStretch(0, 2)
        self.grid_body_upper.setColumnStretch(2, 2)
        # self.grid_body_lower.setColumnStretch(3, 1)

        ### SUPERGRID ###
        self.supergrid = QGridLayout()
        self.supergrid.addLayout(self.grid_top, 0, 0)
        self.supergrid.addLayout(self.grid_body_upper, 1, 0)
        self.supergrid.addLayout(self.grid_body, 2, 0)
        # self.supergrid.addLayout( self.grid_body_lower, 4, 0)
        self.supergrid.addWidget(QHLine(), 6, 0, 1, 2)
        # self.supergrid.addLayout( self.grid_bottom, 6, 0)
        self.supergrid.addLayout(self.grid_body_lower, 7, 0)
        self.supergrid.addWidget(QHLine(), 8, 0, 1, 2)

        # Set layout and window title
        self.setLayout(self.supergrid)
        self.setWindowTitle("Q")

        # Loads self.curr_section as the current image and sets all fields appropriatly
        self.setCurrSection(self.curr_section_index)

    def help_button_press(self, button):
        info_text = "This GUI is used to align slices to each other. The shortcut commands are as follows: \n\n\
    -  `[`: Go back one section. \n\
    -  `]`: Go forward one section."

        QMessageBox.information(self, "Empty Field", info_text)

    def loadImage(self):
        curr_fn = self.valid_sections[self.valid_section_keys[
            self.curr_section_index]]['destination']
        # Get filepath of "curr_section" and set it as viewer's photo
        img_fp = os.path.join(self.fileLocationManager.thumbnail_prep, curr_fn)
        self.viewer.setPhoto(QPixmap(img_fp))

    def photoClicked(self, pos):
        if self.viewer.dragMode() == QGraphicsView.NoDrag:
            print('%d, %d' % (pos.x(), pos.y()))

    def pixInfo(self):
        self.viewer.toggleDragMode()

    def keyPressEvent(self, event):
        try:
            key = event.key()
        except AttributeError:
            key = event

        if key == 91:  # [
            self.getPrevValidSection(self.curr_section_index)
            self.setCurrSection(self.prev_section_index)
        elif key == 93:  # ]
            self.getNextValidSection(self.curr_section_index)
            self.setCurrSection(self.next_section_index)
        else:
            print(key)

    def setCurrSection(self, section_index=-1):
        """
        Sets the current section to the section passed in.
        Will automatically update curr_section, prev_section, and next_section.
        Updates the header fields and loads the current section image.
        """
        if section_index == -1:
            section_index = self.curr_section_index

        # Update curr, prev, and next section
        self.curr_section_index = section_index
        self.curr_section = self.valid_sections[self.valid_section_keys[
            self.curr_section_index]]['destination']
        self.prev_section = self.getPrevValidSection(self.curr_section_index)
        self.next_section = self.getNextValidSection(self.curr_section_index)
        # Update the section and filename at the top
        self.updateCurrHeaderFields()
        # Update the quality selection in the bottom left
        self.loadImage()

    def getNextValidSection(self, section_index):
        self.next_section_index = section_index + 1
        if self.next_section_index > len(self.valid_sections) - 1:
            self.next_section_index = 0
        self.next_section = self.valid_sections[self.valid_section_keys[
            self.next_section_index]]['destination']
        return self.next_section

    def getPrevValidSection(self, section_index):
        self.prev_section_index = int(section_index) - 1
        if self.prev_section_index < 0:
            self.prev_section_index = len(self.valid_sections) - 1
        self.prev_section = self.valid_sections[self.valid_section_keys[
            self.prev_section_index]]['destination']
        return self.prev_section

    def buttonPress(self, button):
        # Brighten an image
        if button in [self.b1, self.b2, self.b3]:
            # "Flip image(s) across central vertical line"
            if button == self.b1:
                self.transform_thumbnails('flip')
            # "Flop image(s) across central horozontal line"
            elif button == self.b2:
                self.transform_thumbnails('flop')
            # "Rotate Image(s)"
            elif button == self.b3:
                self.transform_thumbnails('rotate',
                                          degrees=str(self.cb.currentText()))
            # Update the Viewer info and displayed image
            self.setCurrSection(self.curr_section_index)
        elif button == self.b_done:
            QMessageBox.about(
                self, "Popup Message",
                "All selected operations will now be performed on the\
                full sized raw images. This may take an hour or two, depending on how many operations are queued."
            )
            self.apply_queued_transformations()
            self.finished()

    def updateCurrHeaderFields(self):
        label = self.valid_sections[self.valid_section_keys[
            self.curr_section_index]]['source']
        self.e4.setText(label)
        self.e5.setText(str(self.curr_section))

    def transform_thumbnails(self, transform_type, degrees=0):
        """
        Transform_type must be "rotate", "flip", or "flop".
        These transformations get applied to all the active sections. The actual
        conversions take place on the thumbnails and the raw files.
        The transformed raw files get placed in the preps/oriented dir.
        """
        if transform_type == 'rotate':
            base_cmd = ['convert', '-' + transform_type, str(degrees)]
        else:
            base_cmd = ['convert', '-' + transform_type]

        self.queued_transformations.append(base_cmd)
        # Apply transforms to just the thumbnails
        THUMBNAIL = self.fileLocationManager.prep_thumbnail
        for k, v in self.valid_sections.items():
            thumbnail = os.path.join(THUMBNAIL, v['destination'])
            subprocess.call(base_cmd + [thumbnail, thumbnail])

    def finished(self):
        self.sqlController.set_step_completed_in_progress_ini(
            self.stack, '1-5_setup_orientations')
        # close_main_gui( ex )
        sys.exit(app.exec_())

    def apply_queued_transformations(self):
        print('queued_transformations', self.queued_transformations)
        if self.queued_transformations == []:
            print('No transformations to do. Exit stage left ...')
        else:
            # Apply to "raw" images
            RAW = self.fileLocationManager.tif
            ORIENTED = self.fileLocationManager.oriented
            for base_cmd in tqdm(self.queued_transformations):
                for k, v in self.valid_sections.items():
                    raw = os.path.join(RAW, v['source'])
                    oriented = os.path.join(ORIENTED, v['destination'])
                    subprocess.call(base_cmd + [raw, oriented])
                    #print(base_cmd + [raw, oriented])
        # Clear the queued transformations
        self.queued_transformations = []
Exemple #5
0
class init_GUI(QWidget):
    def __init__(self, stack, parent = None):
        super(init_GUI, self).__init__(parent)
        self.font1 = QFont("Arial",16)
        self.font2 = QFont("Arial",12)

        # Stack specific info, determined from dropdown menu selection
        self.stack = stack
        self.curr_step = ""
        self.sqlController = SqlController()
        self.sqlController.get_animal_info(self.stack)
        self.initUI()

    def initUI(self):
        # Set Layout and Geometry of Window
        self.grid_top = QGridLayout()
        self.grid_buttons = QGridLayout()
        self.grid_bottom = QGridLayout()

        #self.setFixedSize(1000, 450)
        self.resize(1000, 450)

        ### Grid Top (1 row) ###
        # Static Text Field
        self.e1 = QLineEdit()
        self.e1.setValidator( QIntValidator() )
        self.e1.setAlignment(Qt.AlignCenter)
        self.e1.setFont( self.font1 )
        self.e1.setReadOnly( True )
        self.e1.setText( "Align Step: Main Page" )
        self.e1.setFrame( False )
        self.grid_top.addWidget( self.e1, 0, 0)

        ### Grid Buttons ###
        # Button
        self.b_1 = QPushButton("1) Correct automatic alignments")
        format_grid_button_initial( self.b_1 )
        self.b_1.clicked.connect( lambda:self.button_grid_push(self.b_1) )
        self.grid_buttons.addWidget( self.b_1, 0, 0)

        ### Grid Bottom ###
        # Button Text Field
        self.b_exit = QPushButton("Exit")
        self.b_exit.setDefault(True)
        self.b_exit.clicked.connect(lambda:self.button_push(self.b_exit))
        self.grid_bottom.addWidget(self.b_exit, 0, 4)

        #self.grid_buttons.setColumnStretch(1, 3)
        #self.grid_buttons.setRowStretch(1, 2)

        ### SUPERGRID ###
        self.supergrid = QGridLayout()
        self.supergrid.addLayout( self.grid_top, 0, 0)
        self.supergrid.addLayout( self.grid_buttons, 1, 0)
        self.supergrid.addLayout( self.grid_bottom, 2, 0)

        # Set layout and window title
        self.setLayout( self.supergrid )
        self.setWindowTitle("Align to Active Brainstem Atlas - Aligning Slices Page")

        # Update interactive windows
        self.updateFields()

        # Center the GUI
        self.center()

    def updateFields(self):
        # Set stack-specific variables
        try:
            self.stain = self.sqlController.histology.counterstain
            # Check the brains_info/STACK_progress.ini file for which step we're on
            self.curr_step = self.sqlController.get_current_step_from_progress_ini(self.stack)

            # Disable all grid buttons except for the one corresponding to our current step
            self.format_grid_buttons()
        # If there are no stacks/brains that have been started
        except KeyError:
            for grid_button in [self.b_1]:
                format_grid_button_cantStart( grid_button )

    def format_grid_buttons(self):
        """
        Locates where you are in the pipeline by reading the brains_info/STACK_progress.ini

        Buttons corresponding to previous steps are marked as "completed", buttons corresponding
        to future steps are marked as "unpressable" and are grayed out.
        """
        curr_step = self.curr_step

        if '2_align' in curr_step:
            active_button = self.b_1
        else:
            active_button = None
            print(curr_step)

        passed_curr_step = False
        for grid_button in [self.b_1]:
            if not passed_curr_step and grid_button != active_button:
                format_grid_button_completed( grid_button )
            elif grid_button == active_button:
                passed_curr_step = True
                format_grid_button_initial(active_button)
            elif passed_curr_step and grid_button != active_button:
                format_grid_button_cantStart( grid_button )

    def button_grid_push(self, button):
        """
        If any of the "grid" buttons are pressed, this is the callback function.

        In this case, "grid" buttons have a one-to_one correspondance to the steps in the pipeline.
        The completion of each step means you move onto the next one.
        """
        # Alignment Correction GUI
        if button == self.b_1:
            subprocess.call(['python','a_GUI_correct_alignments.py', self.stack])
            self.sqlController.set_step_completed_in_progress_ini(self.stack, '2_align')

        self.updateFields()

    def button_push(self, button):
        """
        Secondary button callback function
        """
        if button == self.b_exit:
            sys.exit( app.exec_() )

    def center(self):
        """
        This function simply aligns the GUI to the center of your monitor.
        """
        frameGm = self.frameGeometry()
        screen = QApplication.desktop().screenNumber( QApplication.desktop().cursor().pos())
        centerPoint = QApplication.desktop().screenGeometry(screen).center()
        frameGm.moveCenter(centerPoint)
        self.move(frameGm.topLeft())

    def closeEvent(self, event):
        sys.exit( app.exec_() )