Beispiel #1
0
    def openfiles(self, paths):
        """
        Override openfiles method in base plugin. Used to open a tomography dataset from the recognized file formats
        and instantiate a viewer.TomoViewer tab. This function takes quite a bit, consider running this in a background
        thread

        Parameters
        ----------
        paths : str/list
            Path to file. Currently only one file is supported. Multiple paths (ie stack of tiffs should be easy to
            implement using the formats.StackImage class.

        """

        msg.showMessage('Loading file...', timeout=10)
        self.activate()
        if type(paths) is list:
            paths = paths[0]

        # # create file name to pass to manager (?)
        # file_name = paths.split("/")[-1]
        # self.working_dir = paths.split(file_name)[0]


        widget = TomoViewer(paths=paths)
        widget.sigSetDefaults.connect(self.manager.setPipelineFromDict)
        widget.wireupCenterSelection(self.manager.recon_function)
        self.centerwidget.addTab(widget, os.path.basename(paths))
        self.centerwidget.setCurrentWidget(widget)
Beispiel #2
0
    def RMC_done(self):
        """
        Slot to receive signal when HipRMC calculation is done. Emits signal to main thread to load output
        """
        run_time = time.time() - self.start_time

        if not self.interrupt:
            os.rename(self.hig_name, '{}/{}.hig'.format(self.rmc_folder, self.save_name))

            # write output of RMC to file in hiprmc output folder
            output_path = self.rmc_folder + "/{}_rmc_output.txt".format(self.save_name)
            with open(output_path, 'w') as txt:
                txt.write(self.output)

            msg.showMessage('HipRMC complete. Run time: {:.2f} s'.format(run_time))
            self.emitter.sigFinished.emit()
        else:
            try:
                os.rename(self.hig_name, '{}/{}.hig'.format(self.rmc_folder, self.save_name))
            except OSError:
                pass

            msg.showMessage('HipRMC interrupted by user. Run time: {:.2f} s'.format(run_time))

        self.interrupt = False
Beispiel #3
0
    def opendirectory(self, files, operation=None):
        """
        Override opendirectory method in base plugin. Used to open a tomography dataset from the recognized file formats
        and instantiate a viewer.TomoViewer tab.

        Currently not completely implemented

        Parameters
        ----------
        paths : str/list
            Path to dir
        """

        msg.showMessage('Loading directory...', timeout=10)
        self.activate()
        try:
            if type(files) is list:
                files = files[0]

            widget = TomoViewer(paths=files)
        except Exception as e:
            msg.showMessage('Unable to load directory. Check log for details.',
                            timeout=10)
            raise e
        widget.sigSetDefaults.connect(self.manager.setPipelineFromDict)
        widget.wireupCenterSelection(self.manager.recon_function)
        self.centerwidget.addTab(widget, os.path.basename(files))
        self.centerwidget.setCurrentWidget(widget)
Beispiel #4
0
    def slicePreviewAction(self,
                           message='Computing slice preview...',
                           fixed_func=None,
                           prange=None):
        """
        Called when a reconstruction preview is requested either by the toolbar button or by the test parameter range
        from a parameter.

        Parameters
        ----------
        message : str, optional
            Message to log. Test Parameters log a different message than the default
        fixed_func : type class
            A dynamic class with only the necessary attributes to be run in a workflow pipeline. This is used for
            parameter range tests to create the class with the parameter to be run and send it to a background thread.
            See FunctionManager.testParameterRange for more details
        prange : dict, optional
            Dictionary containing parameter being tested for TestParamRange, and the function the parameter belongs to
        """
        if self.checkPipeline():
            msg.showMessage(message, timeout=0)
            prev_slice = self.centerwidget.currentWidget(
            ).sinogramViewer.currentIndex
            dims = self.get_reader_dims(sino=(prev_slice, prev_slice + 1, 1))
            dims += (0, )
            self.preview_slices = self.centerwidget.widget(
                self.currentIndex()).sinogramViewer.currentIndex
            self.processFunctionStack(
                callback=lambda *x: self.runSlicePreview(*x),
                dims=dims,
                fixed_func=fixed_func,
                prange=prange)
Beispiel #5
0
    def loadFullReconstruction(self):
        """
        Sets up a full reconstruction for the current dataset based on the current workflow pipeline and configuration
        parameters. Does not run reconstruction if there is one already running. Called when the corresponding toolbar
        button is clicked.
        """
        if not self.checkPipeline():
            return

        value = QtGui.QMessageBox.question(None, 'Run Full Reconstruction',
                                           'You are about to run a full reconstruction. '
                                           'This step can take some minutes. Do you want to continue?',
                                   (QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel))
        if value is QtGui.QMessageBox.Cancel:
            return

        currentWidget = self.centerwidget.widget(self.currentWidget())
        self.manager.updateParameters()

        run_state = self.manager.saveState(currentWidget)



        recon_iter = threads.iterator(callback_slot=self.bottomwidget.log2local,
                            interrupt_signal=self.bottomwidget.local_cancelButton.clicked,
                            finished_slot=self.reconstructionFinished)(self.manager.reconGenerator)
        # pstart = self.ui.config_params.child('Start Projection').value()
        # pend = self.ui.config_params.child('End Projection').value()
        # pstep = self.ui.config_params.child('Step Projection').value()
        # sstart = self.ui.config_params.child('Start Sinogram').value()
        # send = self.ui.config_params.child('End Sinogram').value()
        # sstep =  self.ui.config_params.child('Step Sinogram').value()

        proj = None
        sino = None
        chunk = None
        for f in self.manager.features:
            if 'Reader' in f.name:
                proj = f.projections
                sino = f.sinograms
                chunk = f.chunk

        if (not proj and not sino and not chunk) or (not proj[1] and not sino[1] and not chunk):
            sino = (0, currentWidget.data.shape[2], 1)
            proj = (0, currentWidget.data.shape[0], 1)
            chunk = cpu_count()*5

        args = (currentWidget, run_state, proj, sino, chunk, cpu_count())

        self.manager.recon_queue.put([recon_iter, args])

        if self.recon_running:
            name = self.centerwidget.tabText(self.centerwidget.currentIndex())
            msg.showMessage('Queued reconstruction for {}.'.format(name), timeout=0)

        self.runReconstruction()
Beispiel #6
0
    def reconstructionFinished(self):
        """
        Slot to revieve the reconstruction background threads finished signal. Runs another reconstruction is there is
        one on the queue
        """

        msg.showMessage('Reconstruction complete.', timeout=10)

        self.recon_running = False
        self.runReconstruction()
Beispiel #7
0
    def freeRecon(self):
        """
        Frees plugin to run reconstruction and run next in queue when job is canceled
        """

        msg.showMessage("Reconstruction interrupted.", timeout=0)
        self.bottom.log2local(
            '---------- RECONSTRUCTION INTERRUPTED ----------')
        self.queue_widget.removeRecon(0)
        self.recon_running = False
        self.runReconstruction()
Beispiel #8
0
    def opendirectory(self, files, operation=None):
        msg.showMessage('Loading directory...', timeout=10)
        self.activate()
        if type(files) is list:
            files = files[0]

        widget = TomoViewer(paths=files)
        widget.sigSetDefaults.connect(self.manager.setPipelineFromDict)
        widget.wireupCenterSelection(self.manager.recon_function)
        self.centerwidget.addTab(widget, os.path.basename(files))
        self.centerwidget.setCurrentWidget(widget)
Beispiel #9
0
    def preview3DAction(self):
        """
        Called when a reconstruction 3D preview is requested either by the toolbar button.
        The process is almost equivalent to running a slice preview except a different slice object is passed to extract
        a subsampled array from the raw tomographic array
        """

        if self.checkPipeline():
            msg.showMessage('Computing 3D preview...', timeout=0)
            slc = (slice(None), slice(None, None, 8), slice(None, None, 8))
            self.manager.cor_scale = lambda x: x // 8
            self.processFunctionStack(callback=lambda x: self.run3DPreview(*x), slc=slc)
Beispiel #10
0
    def multiSlicePreviewAction(self,
                                message='Computing multi-slice preview...'):
        """
        Called when a multiple slice reconstructin preview is requested by the toolbar buttong

        Parameters
        ----------
        message : str, optional
            Message to log. Test Parameters log a different message than the default
        """

        slice_no = self.centerwidget.widget(
            self.currentIndex()).sinogramViewer.currentIndex
        maximum = self.centerwidget.widget(
            self.currentIndex()).sinogramViewer.data.shape[0] - 1
        dialog = sliceDialog(parent=self.centerwidget,
                             val1=slice_no,
                             val2=slice_no + 20,
                             maximum=maximum)
        try:
            value = dialog.value

            if value is None:
                pass
            elif type(value) == str:
                msg.showMessage(value, timeout=0)
            else:
                if self.checkPipeline():
                    msg.showMessage(message, timeout=0)
                    if value[0] == value[1]:
                        dims = self.get_reader_dims(sino=(value[1],
                                                          value[1] + 1, 1))
                        dims += (0, )
                        self.preview_slices = value[1]
                        self.centerwidget.widget(
                            self.currentIndex()).sinogramViewer.setIndex(
                                self.preview_slices)
                        self.processFunctionStack(
                            callback=lambda *x: self.runSlicePreview(*x),
                            dims=dims,
                            fixed_func=None)
                    else:
                        dims = self.get_reader_dims(sino=(value[0],
                                                          value[1] + 1, 1))
                        dims += (0, )
                        self.preview_slices = [value[0], value[1]]
                        self.processFunctionStack(
                            callback=lambda *x: self.runSlicePreview(*x),
                            dims=dims,
                            fixed_func=None)
        except AttributeError:
            pass
Beispiel #11
0
 def currentChanged(self, current, previous):
     item = self.itemFromIndex(current)
     try:
         if item.childCount() == 0:
             msg.showMessage('Loading preview...')
             dataset = item.parent().parent().text(0)
             stage = item.parent().text(0)
             bg_get_preview = threads.method(
                 callback_slot=self.sigItemPreview.emit,
                 except_slot=self.handleException)(self.client.get_image_as)
             bg_get_preview(dataset, stage, index=0)
     except AttributeError:
         pass
Beispiel #12
0
    def runReconstruction(self):
        """
        Takes reconstruction job from self.manager.recon_queue and runs it on background thread. Saves function
        pipeline as python runnable after reconstruction is finished.
        """
        if (not self.manager.recon_queue.empty()) and (not self.recon_running):
            self.recon_running = True
            recon_job = self.manager.recon_queue.get()
            args = recon_job[1]
            name = self.centerwidget.tabText(self.centerwidget.indexOf(args[0]))
            msg.showMessage('Computing reconstruction for {}...'.format(name), timeout=0)

            recon_job[0](*args)
Beispiel #13
0
    def reconstructionFinished(self):
        """
        Slot to revieve the reconstruction background threads finished signal. Runs another reconstruction is there is
        one on the queue
        """

        msg.showMessage('Reconstruction complete.', timeout=10)

        self.queue_widget.removeRecon(0)
        if len(self.queue_widget.recon_queue) > 0:
            self.bottom.log2local(
                '------- Beginning next reconstruction -------')
        self.recon_running = False
        self.runReconstruction()
Beispiel #14
0
    def loadFullReconstruction(self):
        """
        Sets up a full reconstruction for the current dataset based on the current workflow pipeline and configuration
        parameters. Does not run reconstruction if there is one already running. Called when the corresponding toolbar
        button is clicked.
        """
        if not self.checkPipeline():
            return

        value = QtGui.QMessageBox.question(
            None, 'Run Full Reconstruction',
            'You are about to run a full reconstruction. '
            'This step can take some minutes. Do you want to continue?',
            (QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel))
        if value is QtGui.QMessageBox.Cancel:
            return

        currentWidget = self.centerwidget.currentWidget()
        self.manager.updateParameters()

        func_dict, theta, center, pipeline_dict, run_dict = self.manager.saveState(
            currentWidget)
        recon_iter = threads.iterator(
            callback_slot=self.bottom.log2local,
            except_slot=self.reconstructionFinished,
            interrupt_signal=self.bottom.local_cancelButton.clicked,
            finished_slot=self.reconstructionFinished)(
                self.manager.reconGenerator)

        # set up information for reconstruction
        proj, sino, width, proj_chunk, sino_chunk = self.get_reader_dims()

        dims = (proj, sino, width, sino_chunk, proj_chunk, cpu_count())
        args = (currentWidget, func_dict, theta, center, pipeline_dict,
                run_dict, dims)

        self.queue_widget.recon_queue.append([recon_iter, args])
        self.queue_widget.addRecon(args)

        if self.recon_running:
            name = self.centerwidget.tabText(self.centerwidget.currentIndex())
            msg.showMessage('Queued reconstruction for {}.'.format(name),
                            timeout=0)

        self.runReconstruction()
Beispiel #15
0
    def openfiles(self, paths):
        """
        Override openfiles method in base plugin. Used to open a tomography dataset from the recognized file formats
        and instantiate a viewer.TomoViewer tab. This function takes quite a bit, consider running this in a background
        thread

        Parameters
        ----------
        paths : str/list
            Path to file. Currently only one file is supported. Multiple paths (ie stack of tiffs should be easy to
            implement using the formats.StackImage class.

        """
        msg.showMessage('Loading file...', timeout=10)
        self.activate()

        try:
            if type(paths) is list:
                paths = paths[0]
            widget = TomoViewer(toolbar=self.toolbar, paths=paths)
        except Exception as e:
            msg.showMessage('Unable to load file. Check log for details.',
                            timeout=10)
            raise e

        # connect signals
        widget.sigSetDefaults.connect(self.manager.setPipelineFromDict)
        widget.projectionViewer.sigROIWidgetChanged.connect(
            lambda x: x.sigRegionChanged.connect(self.manager.
                                                 adjustReaderParams))

        # complicated way of connecting the ROI params to the functionwidget
        # is there a better way to do this?
        self.manager.sigNormFuncAdded.connect(lambda x: x.sigROIAdded.connect(
            widget.projectionViewer.stackViewer.view.addItem))
        self.manager.sigNormFuncAdded.connect(lambda x: x.sigROIAdded.connect(
            lambda y: y.sigRegionChanged.connect(lambda z: x.adjustParams(
                self.manager))))

        self.wireCORWidgets(widget)
        self.centerwidget.addTab(widget, os.path.basename(paths))
        self.centerwidget.setCurrentWidget(widget)
Beispiel #16
0
    def runDask(self):
        import client.dask_active_executor

        if client.dask_active_executor.active_executor is None:
            #warning message
            return

        ae = client.dask_active_executor.active_executor.executor

        def hipgisaxs_func(yaml_str):
            import subprocess
            import time
            timestamp = time.strftime("%Y.%m.%d.%H.%M.%S")
            filename = os.path.join(os.path.expanduser('~'), "test_remote.yml")

            with open(filename, 'w') as outfile:
                outfile.write(yaml_str)

            a = subprocess.check_output([
                "srun", "--job-name=hipgisaxs", "--nodes=1", "--ntasks=1",
                "--ntasks-per-node=1", "--time=00:30:00", "/bin/bash",
                "/users/course79/rungisaxs.sh", filename
            ])
            return a

        self.writeyaml()

        with open(os.path.join(os.path.expanduser('~'), 'test.yml'),
                  'r') as outfile:
            fx_str = outfile.read()

        msg.showMessage('Submitting job to remote executor...')
        future_tag = ae.submit(hipgisaxs_func, fx_str, pure=False)
        msg.showMessage('Job received. Submitting to queue...')

        import time
        while future_tag.status == "pending":
            #msg.showMessage("Waiting for response from server...",timeout=5)
            time.sleep(1)

        if future_tag.status == "failure":
            msg.showMessage("Execution failed.", timeout=5)
            return

        msg.showMessage("Execution complete. Fetching result...", timeout=5)
        result = future_tag.result()
        out = np.array(
            [np.fromstring(line, sep=' ') for line in result.splitlines()])
        msg.logMessage(("result = ", out), msg.DEBUG)

        plugins.plugins['Viewer'].instance.opendata(out)
    def serve(self):
        msg.logMessage("Serving: " + self.command, msg.INFO)
        channel = self.client.get_transport().open_session()
        msg.logMessage(channel.get_pty(), msg.DEBUG)
        # channel.exec_command('tty')
        channel.exec_command(self.command)
        readytorun = False
        while True:
            if channel.exit_status_ready():
                break
            rl, wl, xl = select.select([channel], [], [], 10.0)
            if len(rl) > 0:
                line = channel.recv(1024)
                msg.logMessage(line)
                if 'queued and waiting for resources' in line:
                    msg.showMessage(
                        'Execution queued and waiting for resources...')
                elif 'has been allocated resources' in line:
                    msg.showMessage(
                        'Execution has been allocated resources...')
                    readytorun = True
                if readytorun and line:
                    msg.showMessage('Executing job...')
                    readytorun = False

                if line.find("Password") >= 0:
                    msg.logMessage("writing password", msg.DEBUG)
                    channel.sendall(self.password + "\n")
        msg.logMessage("Ending Dask Scheduler", msg.INFO)
Beispiel #18
0
    def multiSlicePreviewAction(self, message='Computing multi-slice preview...', fixed_func=None):

        slice_no = self.centerwidget.widget(self.currentWidget()).sinogramViewer.currentIndex
        maximum = self.centerwidget.widget(self.currentWidget()).sinogramViewer.data.shape[0]-1
        dialog = sliceDialog(parent=None, val1=slice_no, val2=slice_no+20,maximum=maximum)
        try:
            value = dialog.value

            if value is None:
                pass
            elif type(value) == str:
                msg.showMessage(value,timeout=0)
            else:
                if self.checkPipeline():
                    msg.showMessage(message, timeout=0)
                    if value[0] == value[1]:
                        self.preview_slices = value[1]
                        self.processFunctionStack(callback=lambda x: self.runSlicePreview(*x),fixed_func=fixed_func)
                    else:
                        self.preview_slices = [value[0],value[1]]
                        slc = (slice(None,None,None), slice(value[0],value[1]+1,1), slice(None,None,None))
                        self.processFunctionStack(callback=lambda x: self.runSlicePreview(*x), slc=slc, fixed_func=fixed_func)
        except AttributeError:
            pass
Beispiel #19
0
    def preview3DAction(self):
        """
        Called when a reconstruction 3D preview is requested either by the toolbar button.
        The process is almost equivalent to running a slice preview except a different slice object is passed to extract
        a subsampled array from the raw tomographic array. User chooses subsample factor from pop-up window.
        """

        if self.checkPipeline():

            window = QtGui.QInputDialog(self.centerwidget)
            window.setIntValue(8)
            window.setWindowTitle('3D Preview subsample factor')
            window.setLabelText(
                'Choose a subsample factor for the 3D preview: ')
            window.exec_()
            val = window.intValue()

            if window.result():
                msg.showMessage('Computing 3D preview...', timeout=0)
                dims = self.get_reader_dims(sino=(None, None, val),
                                            width=(None, None, val))
                dims += (0, )
                self.processFunctionStack(
                    callback=lambda *x: self.run3DPreview(*x), dims=dims)
Beispiel #20
0
    def runFullReconstruction(self):
        """
        Sets up a full reconstruction to be run in a background thread for the current dataset based on the current
        workflow pipeline and configuration parameters. Called when the corresponding toolbar button is clicked.

        Made obsolete by loadFullReconstruction and runReconstruction
        """
        if not self.checkPipeline():
            return

        value = QtGui.QMessageBox.question(None, 'Run Full Reconstruction',
                                           'You are about to run a full reconstruction. '
                                           'This step can take some minutes. Do you want to continue?',
                                   (QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel))
        if value is QtGui.QMessageBox.Cancel:
            return

        name = self.centerwidget.tabText(self.centerwidget.currentIndex())
        msg.showMessage('Computing reconstruction for {}...'.format(name),timeout = 0)
        self.bottomwidget.local_console.clear()
        self.manager.updateParameters()
        recon_iter = threads.iterator(callback_slot=self.bottomwidget.log2local,
                                    interrupt_signal=self.bottomwidget.local_cancelButton.clicked,
                                    finished_slot=self.reconstructionFinished)(self.manager.functionStackGenerator)
Beispiel #21
0
    def runSlicePreview(self,
                        datawidget,
                        func_dict,
                        theta,
                        center,
                        stack_dict,
                        prange=None,
                        dims=None):
        """
        Callback function that receives the necessary widgets/information required to run a preview and
        add it to the viewer.TomoViewer.previewViewer

        Parameters
        ----------
        datawidget : viewers.TomoViewer
            Widget containing dataset
        func_dict: dict
            Dictionary of function names and partials with keywords for the reconstruction
        theta: list
            List of values representing angular location of camera (for reconstruction)
        center: float
            Center of rotation of dataset
        stack_dict : dict
            Dictionary describing the workflow pipeline being run. This is displayed to the left of the preview image in
            the viewer.TomoViewer.previewViewer
        prange: dict, optional
            Dictionary containing parameter being tested for TestParamRange, and the function the parameter belongs to
        dims : tuple, optional
            Tuple containing dimensions of dataset to be reconstructed
        """

        callback = partial(self.centerwidget.currentWidget().addSlicePreview,
                           stack_dict,
                           slice_no=self.preview_slices,
                           prange=prange)
        err_message = 'Unable to compute slice preview. Check log for details.'

        except_slot = lambda: msg.showMessage(err_message)
        bg_fold = threads.iterator(callback_slot=callback,
                                   finished_slot=msg.clearMessage,
                                   lock=threads.mutex,
                                   except_slot=except_slot)
        bg_fold(self.manager.reconGenerator)(datawidget, func_dict, theta,
                                             center, None, None, dims, None,
                                             'Slice')
Beispiel #22
0
    def run3DPreview(self,
                     datawidget,
                     func_dict,
                     theta,
                     center,
                     stack_dict,
                     prange=None,
                     dims=None):
        """
        Callback function that receives the partial stack and corresponding dictionary required to run a preview and
        add it to the viewer.TomoViewer.preview3DViewer

        Parameters
        ----------
        datawidget : viewers.TomoViewer
            Widget containing dataset
        func_dict: dict
            Dictionary of function names and partials with keywords for the reconstruction
        theta: list
            List of values representing angular location of camera (for reconstruction)
        center: float
            Center of rotation of dataset
        stack_dict : dict
            Dictionary describing the workflow pipeline being run. This is displayed to the left of the preview image in
            the viewer.TomoViewer.previewViewer
        dims : tuple, optional
            Tuple containing dimensions of dataset to be reconstructed
        """

        self.manager.updateParameters()
        callback = partial(
            self.centerwidget.widget(self.currentIndex()).add3DPreview,
            stack_dict)
        err_message = 'Unable to compute 3D preview. Check log for details.'
        except_slot = lambda: msg.showMessage(err_message)
        bg_fold = threads.iterator(callback_slot=callback,
                                   finished_slot=msg.clearMessage,
                                   lock=threads.mutex,
                                   except_slot=except_slot)
        bg_fold(self.manager.reconGenerator)(datawidget, func_dict, theta,
                                             center, None, None, dims, None,
                                             '3D')
Beispiel #23
0
    def foldPreviewStack(self, partial_stack, initializer, data_dict, callback, error_message):
        """
        Calls the managers foldFunctionStack on a background thread. This is what tells the manager to compute a
        slice preview or a 3D preview from a specified workflow pipeline

        Parameters
        ----------
        partial_stack : list of functools.partial
            List of partials that require only the input array to run.
        initializer : ndarray
            Array to use as initializer for folding operation
        callback : function
            function to be called with the return value of the fold (ie the resulting reconstruction).
            This is the current TomoViewers addSlicePreview or add3DPreview methods
        error_message : str
            Message to log/display if the fold process raises an exception
        """

        except_slot = lambda: msg.showMessage(error_message)
        bg_fold = threads.method(callback_slot=callback, finished_slot=msg.clearMessage, lock=threads.mutex,
                                 except_slot=except_slot)
        # bg_fold(self.manager.foldFunctionStack)(partial_stack, initializer)
        bg_fold(self.manager.foldSliceStack)(partial_stack, data_dict)
Beispiel #24
0
    def __init__(self, paths, worker, parent=None):
        """
        Class that holds image to be processed by HipRMC, image after it has been centered, and HipRMC output

        Attributes
        ----------
        emitter : threads.Emitter
            Holds and emits a signal when fHipRMc done processing
        interrupt : bool
            flag - set true if rmc processing was interrupted; affects post-rmc processes
        cameraLocation : tuple
            2-tuple (x,y) of camera location on input image
        rmcView : ximcam.RmcView.rncView
            Timeline viewer which holds and displays HipRMC output
        orig_image: np.array
            Original input image
        edited_image : np.array
            Image with camera location adjusted to its center
        orig_view : pyqtgraph.ImageView
            Holds the original image
        edited_view : pyqtgraph.ImageView
            Holds the image after camera location adjustment
        image_holder : QtGui.StackedWidget
            Main widget of plugin. Holds original and edited images, as well as HipRMC output, in tabs
        scatteringParams : pyqtgraph.parametertree
            Occupies right side of main widget. Holds configparams
        configparams : pyqtgraph.Parameter
            Class held by scatteringParams which holds parameter values for HipRMC
        output, err : str
            Output and error from HipRMC subprocess call
        headings : QtGui.QTabBar
            Displays name of corresponding tab of image_holder

        Parameters
        ----------
        paths : str/list of str
            Path to input dataset
        worker: threads.Worker
            Worker which queues up jobs and runs them on a QtCore.QThreadpool
        parent : QtGui.QWidget
            parent widget
        args
            Additional arguments
        kwargs
            Additional keyword arguments
        """


        super(inOutViewer, self).__init__(parent=parent)

        self.emitter = threads.Emitter()
        self.interrupt = False
        self.cameraLocation = config.activeExperiment.center
        self.rmc_view= None
        self.edited_image = None
        self.worker = worker


        # holders for original and edited images
        self.orig_view = LogViewer()
        self.orig_view.setContentsMargins(0,0,0,0)
        self.edited_view = LogViewer()
        self.edited_view.setContentsMargins(0,0,0,0)

        if type(paths) == list:
            self.path = paths[0]
        else:
            self.path = paths

        self.image_holder = QtGui.QStackedWidget()
        self.image_holder.setContentsMargins(0,0,0,0)

        # configuring right widget
        sideWidget = QtGui.QWidget()
        sideWidgetFormat = QtGui.QVBoxLayout()
        sideWidgetFormat.setContentsMargins(0, 0, 0, 0)

        # if paths is None, inOutViewer will only hold HipRMC output and the images/parameter table are not necessary
        if paths is not None:

            self.orig_image = np.transpose(loader.loadimage(self.path))
            if len(self.orig_image.shape) > 2:
                self.orig_image = np.transpose(self.orig_image).swapaxes(0,1)
                while len(self.orig_image.shape) > 2:
                    self.orig_image = self.orig_image[:,:,0]
            self.orig_view.setImage(self.orig_image)
            self.orig_view.autoRange()
            try:
                start_size = max(self.orig_image.shape)/10
            except ValueError:
                msg.showMessage("Image must be 2-D")

            scatteringHolder = QtGui.QStackedWidget()

            image_name = self.path.split('/')[-1].split('.')[0]
            self.scatteringParams = pt.ParameterTree()
            params = [{'name': 'Num tiles', 'type': 'int', 'value': 1, 'default': 1},
                      {'name': 'Loading factor', 'type': 'float', 'value': 0.5, 'default': 0.5},
                      {'name': 'Scale factor', 'type': 'int', 'value': 32, 'default': 32},
                      {'name': 'Numsteps factor', 'type': 'int', 'value': 100, 'default': 100},
                      {'name': 'Model start size', 'type': 'int', 'value': start_size},
                      {'name': 'Save name', 'type': 'str', 'value': 'hiprmc_' + image_name},
                      {'name': 'Mask image', 'type': 'str'}]
            self.configparams = pt.Parameter.create(name='Configuration', type='group', children=params)
            self.scatteringParams.setParameters(self.configparams, showTop=False)
            scatteringHolder.addWidget(self.scatteringParams)

            # # is there a better way to check for correct dimensions?
            # if len(self.orig_image.shape) > 2:
            #     shape = (self.orig_image.shape[1], self.orig_image.shape[2])
            # else:
            #     shape = self.orig_image.shape

            self.drawROI(0, 0, self.orig_image.shape[0], self.orig_image.shape[1], 'r',
                         self.orig_view.getImageItem().getViewBox())

            scatteringHolder.setFixedHeight(300)
            sideWidgetFormat.addWidget(scatteringHolder)

        centerButton = QtGui.QPushButton("Center camera location")
        runButton = QtGui.QPushButton("Run RMC processing")
        stopButton = QtGui.QPushButton("Stop RMC")
        sideWidgetFormat.addSpacing(5)
        sideWidgetFormat.addWidget(centerButton)
        sideWidgetFormat.addSpacing(5)
        sideWidgetFormat.addWidget(runButton)
        sideWidgetFormat.addSpacing(5)
        sideWidgetFormat.addWidget(stopButton)
        sideWidgetFormat.addStretch(10)
        sideWidget.setLayout(sideWidgetFormat)

        # connect buttons to processing
        centerButton.clicked.connect(self.center)
        runButton.clicked.connect(self.runRMC)
        stopButton.clicked.connect(self.stop_threads)

        # tab headings for main widget
        self.headings = QtGui.QTabBar(self)
        self.headings.addTab('Original Image')
        self.headings.addTab('Recentered Image')
        self.headings.addTab('RMC Timeline')
        self.headings.addTab('FFT RMC Timeline')
        self.headings.setShape(QtGui.QTabBar.TriangularSouth)


        leftWidget = QtGui.QWidget()
        sidelayout = QtGui.QVBoxLayout()
        sidelayout.addWidget(self.image_holder)
        sidelayout.addWidget(self.headings)
        leftWidget.setLayout(sidelayout)

        fullPlugin = QtGui.QSplitter()
        fullPlugin.addWidget(leftWidget)
        fullPlugin.addWidget(sideWidget)

        h = QtGui.QHBoxLayout()
        h.setContentsMargins(0, 0, 0, 0)
        h.addWidget(fullPlugin)
        self.setLayout(h)

        self.image_holder.addWidget(self.orig_view)
        self.image_holder.addWidget(self.edited_view)

        self.headings.currentChanged.connect(self.currentChanged)
        self.image_holder.currentChanged.connect(self.headings.setCurrentIndex)
Beispiel #25
0
 def getDatasets(self, query):
     msg.showMessage('Searching SPOT database...')
     search = threads.method(callback_slot=self.createDatasetDictionary,
                             finished_slot=msg.clearMessage)(
                                 self.client.search)
     search(query, **self.search_params)
Beispiel #26
0
 def handleException(self, ex, tb):
     msg.showMessage('Unable to fetch preview from SPOT.')
     msg.logMessage(ex, level=40)
Beispiel #27
0
 def hiprmc_not_found(self):
     """
     Slot to receive exception signal in case hiprmc is not found.
     """
     msg.showMessage('Cannot find HipRMC executable. Cannot run HipRMC.')
     QtGui.QMessageBox.critical(self, 'Error', 'Cannot find HipRMC executable. Cannot run HipRMC.')
Beispiel #28
0
    def runRMC(self):
        """
        Slot to receive signal when user requests HipRMC calculation. Writes hig file of parameter values and
        calls HipRMC as subprocess
        """


        msg.showMessage('Running RMC for centered version of {}'.format(self.path), timeout=0)

        if self.rmc_view is not None:
            self.image_holder.removeWidget(self.rmc_view)

        if self.edited_image is None:
            msg.showMessage('Error: must center image before running HipRMC',timeout = 0)
            msg.clearMessage()
            return



        params = self.configparams

        hig_info = {'hipRMCInput': {'instrumentation': {'inputimage': "{}".format(self.write_path_sample),
                                             'imagesize': [self.new_dim, self.new_dim ],
                                             'numtiles': params.child('Num tiles').value(),
                                             'loadingfactors': [params.child('Loading factor').value()]},
                         'computation': {'runname': "{}".format(params.child('Save name').value()),
                                         'modelstartsize': [params.child('Model start size').value(),
                                                            params.child('Model start size').value()],
                                         'numstepsfactor': params.child('Numsteps factor').value(),
                                         'scalefactor': params.child('Scale factor').value()}}}

        self.mask_path = params.child('Mask image').value()
        if self.mask_path and self.mask_path != "None":
            self.mask = np.transpose(loader.loadimage(self.mask_path))
            self.center(False)
            hig_info['hipRMCInput']['instrumentation']['maskimage'] = "{}".format(self.write_path_mask)

        h = hig.hig(**hig_info)
        self.hig_name = os.path.join(os.path.abspath('.'), params.child('Save name').value())

        if not self.hig_name.endswith('.hig'):
            self.hig_name += '.hig'

        # write hig file to disk
        h.write(self.hig_name)
        self.save_name = params.child('Save name').value()
        self.start_time = time.time()

        # starts filewatcher to watch for new hiprmc folder, and the HipRMC job
        # also starts worker if it is not already running
        process = threads.RunnableMethod(method = self.run_RMCthread, finished_slot = self.RMC_done,
                                         except_slot=self.hiprmc_not_found)
        self.file_watcher = NewFolderWatcher(path=os.path.abspath("."), experiment=None)

        # when filewatcher gets rmc folder, it passes it to self.start_watcher to start another watcher
        self.file_watcher.sigFinished.connect(self.start_watcher)
        watcher = threads.RunnableMethod(method=self.file_watcher.run,)
        self.worker.queue.put(watcher)
        self.worker.queue.put(process)

        if not self.worker.isRunning():
            self.worker.start()
Beispiel #29
0
    def __init__(self, app):
        QtCore.QObject.__init__(self, app)
        print 'Gui:\t\t\t', QtGui.QApplication.instance().thread()
        QtGui.QFontDatabase.addApplicationFont("xicam/gui/zerothre.ttf")

        import plugins

        config.activate()

        self._pool = None
        # Load the gui from file
        self.app = app
        guiloader = QUiLoader()
        f = QtCore.QFile("xicam/gui/mainwindow.ui")
        f.open(QtCore.QFile.ReadOnly)
        self.ui = guiloader.load(f)
        f.close()

        # STYLE
        with open('xicam/gui/style.stylesheet', 'r') as f:
            style = f.read()
        app.setStyleSheet(qdarkstyle.load_stylesheet() + style)
        app.setAttribute(QtCore.Qt.AA_DontShowIconsInMenus, False)

        # INITIAL GLOBALS
        self.viewerprevioustab = -1
        self.timelineprevioustab = -1
        self.experiment = config.experiment()
        self.folderwatcher = watcher.newfilewatcher()
        self.plugins = []

        # ACTIONS
        # Wire up action buttons
        self.ui.findChild(QtGui.QAction,
                          'actionOpen').triggered.connect(self.dialogopen)
        self.ui.findChild(QtGui.QAction, 'actionSettings').triggered.connect(
            self.settingsopen)
        self.ui.findChild(QtGui.QAction, 'actionQuit').triggered.connect(
            QtGui.QApplication.instance().quit)

        self.ui.actionExport_Image.triggered.connect(self.exportimage)

        # Grab status bar
        msg.statusbar = self.ui.statusbar
        pb = QtGui.QProgressBar()
        pb.setSizePolicy(QtGui.QSizePolicy.Expanding,
                         QtGui.QSizePolicy.Ignored)
        msg.progressbar = pb
        pb.setAccessibleName('progressbar')
        msg.statusbar.addPermanentWidget(pb)
        pb.hide()
        msg.showMessage('Ready...')
        xglobals.statusbar = self.ui.statusbar  # TODO: Deprecate this by replacing all statusbar calls with msg module

        # PLUG-INS

        placeholders = [
            self.ui.viewmode, self.ui.sidemode, self.ui.bottommode,
            self.ui.toolbarmode, self.ui.leftmode
        ]

        plugins.initplugins(placeholders)

        plugins.plugins['MOTD'].instance.activate()

        plugins.base.fileexplorer.sigOpen.connect(self.openfiles)
        plugins.base.fileexplorer.sigFolderOpen.connect(self.openfolder)
        plugins.base.booltoolbar.actionTimeline.triggered.connect(
            plugins.base.filetree.handleOpenAction)

        pluginmode = plugins.widgets.pluginModeWidget(plugins.plugins)
        self.ui.modemenu.addWidget(pluginmode)

        self.ui.menubar.addMenu(plugins.buildactivatemenu(pluginmode))

        # TESTING
        ##
        # self.openimages(['../samples/AgB_00016.edf'])
        # self.openimages(['/Users/rp/Data/LaB6_Ant1_dc002p.mar3450'])

        # self.calibrate()
        # self.updatepreprocessing()
        ##
        testmenu = QtGui.QMenu('Testing')
        testmenu.addAction('Single frame').triggered.connect(self.singletest)
        testmenu.addAction('Image stack').triggered.connect(self.stacktest)
        testmenu.addAction('Timeline').triggered.connect(self.timelinetest)
        testmenu.addAction('Tilt').triggered.connect(self.tilttest)

        self.ui.menubar.addMenu(testmenu)

        # DASK WORKFLOW
        # TODO turn this into a class

        # convert the following into a class
        self.sessions = ["localhost", "Andromeda", "Daint", "NERSC/Edison"]
        self.session_machines = [
            "localhost", "andromeda.dhcp.lbl.gov", "148.187.1.7",
            "edison.nersc.gov"
        ]
        # self.session_address = ["localhost", socket.gethostbyname("andromeda.dhcp.lbl.gov"), "148.187.26.16", ""]
        self.session_address = [
            "localhost", "andromeda.dhcp.lbl.gov", "148.187.26.16", ""
        ]
        self.session_exec = [
            "", "/home/hari/runscript.sh", "/users/course79/runscript.sh",
            "/usr/common/graphics/visit/camera/runscript.sh"
        ]
        self.executors = [None, None, None, None]

        self.sessionmenu = QtGui.QMenu('Sessions')

        # comboBoxAction = ComboBoxAction("Active Session", self.sessionmenu);

        self.actionGroup = QtGui.QActionGroup(self.sessionmenu)
        for i in self.sessions:
            action = QtGui.QAction(i, self.sessionmenu, checkable=True)
            if i == "localhost":
                action.setChecked(True)
            action.triggered.connect(self.activesessionchanged)
            self.actionGroup.addAction(action)
            self.sessionmenu.addAction(action)

        # self.comboBoxAction.comboBox().activated.connect(self.activesessionchanged)
        # self.sessionmenu.addAction(comboBoxAction)
        self.ui.menubar.addMenu(self.sessionmenu)

        # self.daskLoop = client.dask_io_loop.DaskLoop()
        # try:
        #     # create a local active executor
        #     local_scheduler = client.dask_local_scheduler.LocalScheduler(self.daskLoop)
        #     local_scheduler.execute()
        #     self.executors[0] = local_scheduler
        #     self.sessionmenu.setTitle("Active Session (localhost)")
        #     client.dask_active_executor.active_executor = local_scheduler
        # except:
        #     msg.logMessage("Issues connecting to localhost",msg.ERROR)

        # START PYSIDE MAIN LOOP
        # Show UI and end app when it closes
        self.ui.installEventFilter(self)
Beispiel #30
0
    def center(self, sample=True):
        """
        Slot to receive signal when user requests a centered image. Performs centering and writes new image into
        current working directory

        Parameters
        ----------
        sample: boolean, optional
            flag whether image to be centered is the original sample or the mask image
        """

        if sample:
            if self.edited_image is not None:
                msg.showMessage('Image already centered.')
                return

            image = self.orig_image
        else:
            image = self.mask

        #resize image so that it's in center and displays output if a sample image
        xdim = int(image.shape[0])
        ydim = int(image.shape[1])

        newx = xdim + 2*abs(self.cameraLocation[0]-xdim/2)
        newy = ydim + 2*abs(self.cameraLocation[1]-ydim/2)
        self.new_dim = max(newx,newy)

        self.edited_image = np.ones((self.new_dim,self.new_dim),dtype = np.int)
        new_center = (self.new_dim/2,self.new_dim/2)

        lowleft_corner_x = int(new_center[0]-self.cameraLocation[0])
        lowleft_corner_y = int(new_center[1]-self.cameraLocation[1])

        self.edited_image[lowleft_corner_x:lowleft_corner_x+xdim,lowleft_corner_y: lowleft_corner_y+ydim] = image

        # save image
        if sample:
            self.write_path = self.path

            if self.write_path.endswith('.tif'):
                self.write_path = self.write_path[:-4] + '_centered.tif'
            else:
                self.write_path += '_centered.tif'
            self.write_path_sample = self.write_path

            img = tifimage.tifimage(np.rot90((self.edited_image.astype(float) /
                                              self.edited_image.max() * 2 ** 16).astype(np.int16)))
        else:
            self.write_path = self.mask_path

            if self.write_path.endswith('.tif'):
                self.write_path = self.write_path[:-4] + '_centered.tif'
            else:
                self.write_path += '_centered.tif'
            self.write_path_mask = self.write_path

            img = tifimage.tifimage(np.rot90(self.edited_image.astype(float)))




        img.write(self.write_path)

        if sample:
            self.edited_view.setImage(self.edited_image)

            box = self.drawCameraLocation(self.edited_view,new_center)
            self.drawROI(lowleft_corner_x,lowleft_corner_y,xdim,ydim,'r', box)
            self.drawROI(0,0,self.new_dim,self.new_dim, 'b', box)

            # this is a temporary fix for a problem: pushing a button changes tab back to first
            self.image_holder.setCurrentIndex(1)