Ejemplo n.º 1
0
class XPCSProcessor(ParameterTree):
    def __init__(self, *args, **kwargs):
        super(XPCSProcessor, self).__init__()
        self._paramName = 'Algorithm'
        self._name = 'XPCS Processor'
        self.workflow = None
        self.param = None
        self._workflows = dict()

        self.listParameter = ListParameter(name=self._paramName,
                                           values={'': ''},
                                           value='')

        self.param = Parameter(children=[self.listParameter], name=self._name)
        self.setParameters(self.param, showTop=False)

    def update(self, *_):
        for child in self.param.childs[1:]:
            child.remove()

        self.workflow = self._workflows.get(self.listParameter.value().name,
                                            self.listParameter.value()())
        self._workflows[self.workflow.name] = self.workflow
        for process in self.workflow.processes:
            self.param.addChild(process.parameter)
Ejemplo n.º 2
0
class CorrelationParameterTree(ParameterTree):
    """Parameter tree that captures XPCS correlation adjustable parameters.

    Starting point to attempt to allow selecting an 'algorithm'
    and then repopulating the parameter tree accordingly.
    Any visible input parameters in the associated workflow will be adjustable here.
    The workflow can also be run here.
    """
    def __init__(self, parent=None, showHeader=True, processor: Callable[[], None] = None):
        """Create the parameter tree, optionally providing a workflow.

        When a workflow is provided,

        Parameters
        ----------
        parent
            See pyqtgraph.ParameterTree.__init__.
        showHeader
            See pyqtgraph.ParameterTree.__init__.
        processor
            If provided, creates a 'Run' button that is connected to the callable passed (default is None).
            For example, this callable could grab the necessary data to pass into a workflow, then execute it.
        """
        super(CorrelationParameterTree, self).__init__(parent, showHeader)
        self._paramName = 'Algorithm'
        self._name = 'Correlation Processor'
        self.processor = processor
        self.param = None
        self.workflow = None
        self._workflows = dict()

        # List of algorithms available
        # key   -> algorithm name (workflow.name)
        # value -> algorithm callable (workflow)
        self.listParameter = ListParameter(name=self._paramName,
                                           values={'':''},
                                           value='')

        self.param = Parameter(name=self._name)
        self.param.addChild(self.listParameter)
        self.setParameters(self.param, showTop=False)

        if self.processor:
            # Button added separately since update removes then adds all children in self.param
            self.processButton = ActionParameter(name="Run")
            self.processButton.sigActivated.connect(self.processor)
            self.addParameters(self.processButton)

    def update(self, *_):
        """Update the parameter tree according to which algorithm (workflow) is selected."""
        # for child in self.param.children():  # this doesn't seem to work...
        for child in self.param.childs[1:]:
            child.remove()

        # Based on current workflow (listParameter value), re-populate the tree.
        self.workflow = self._workflows.get(self.listParameter.value().name, self.listParameter.value()())
        self._workflows[self.workflow.name] = self.workflow
        for operation in self.workflow.operations:
            self.param.addChild(Parameter(name=operation.name, type='group', children=operation.as_parameter()))
Ejemplo n.º 3
0
class DeviceProfiles(SettingsPlugin):
    sigRequestRedraw = Signal()
    sigRequestReduce = Signal()
    sigSimulateCalibrant = Signal()

    name = 'Device Profiles'

    def __init__(self):
        self.headermodel = None
        self.selectionmodel = None
        self.multiAI = MultiGeometry([])
        self.AIs = dict()

        widget = ParameterTree()
        energy = SimpleParameter(name='Energy',
                                 type='float',
                                 value=10000,
                                 siPrefix=True,
                                 suffix='eV')
        wavelength = SimpleParameter(name='Wavelength',
                                     type='float',
                                     value=1.239842e-6 / 10000,
                                     siPrefix=True,
                                     suffix='m')
        self.parameter = Parameter(name="Device Profiles",
                                   type='group',
                                   children=[energy, wavelength])
        widget.setParameters(self.parameter, showTop=False)
        icon = QIcon(str(path('icons/calibrate.png')))
        super(DeviceProfiles, self).__init__(icon, "Device Profiles", widget)

        self.parameter.sigValueChanged.connect(self.sigRequestRedraw)
        self.parameter.sigValueChanged.connect(self.sigRequestReduce)
        self.parameter.sigTreeStateChanged.connect(self.simulateCalibrant)
        self.parameter.sigTreeStateChanged.connect(self.genAIs)

        self.parameter.sigValueChanged.connect(self.simulateCalibrant)

    def simulateCalibrant(self, *args):
        self.sigSimulateCalibrant.emit()

    def genAIs(self, parent, changes):
        for parameter, key, value in changes:
            if parameter.name == 'Wavelength':
                self.parameter.param('Energy').setValue(
                    1.239842e-6 / self.param('Wavelength').value(),
                    blockSignal=self.parameter.sigTreeStateChanged)
            elif parameter.name == 'Energy':
                self.parameter.param('Wavelength').setValue(
                    1.239842e-6 / self.param('Energy').value(),
                    blockSignal=self.WavelengthChanged)

        for parameter in self.parameter.children():
            if isinstance(parameter, DeviceParameter):
                device = parameter.name()
                ai = self.AI(device)
                ai.set_wavelength(self.parameter['Wavelength'])
                ai.detector = parameter['Detector']()
                ai.detector.set_binning([parameter['Binning']] * 2)
                ai.detector.set_pixel1(parameter['Pixel Size X'])
                ai.detector.set_pixel2(parameter['Pixel Size Y'])
                fit2d = ai.getFit2D()
                fit2d['centerX'] = parameter['Center X']
                fit2d['centerY'] = parameter['Center Y']
                fit2d['directDist'] = parameter['Detector Distance'] * 1000
                fit2d['tilt'] = parameter['Detector Tilt']
                fit2d['tiltPlanRotation'] = parameter['Detector Rotation']
                ai.setFit2D(**fit2d)

    def AI(self, device):
        if device not in self.AIs:
            self.addDevice(device)
        return self.AIs[device]

    def setAI(self, ai: AzimuthalIntegrator, device: str):
        self.AIs[device] = ai
        self.multiAI.ais = self.AIs.values()

        # propagate new ai to parameter
        fit2d = ai.getFit2D()
        try:
            self.setSilence(True)
            self.parameter.child(device,
                                 'Detector').setValue(type(ai.detector))
            self.parameter.child(device,
                                 'Binning').setValue(ai.detector.binning[0])
            self.parameter.child(device, 'Detector Tilt').setValue(
                fit2d['tiltPlanRotation'])
            self.parameter.child(device,
                                 'Detector Rotation').setValue(fit2d['tilt'])
            self.parameter.child(device, 'Pixel Size X').setValue(ai.pixel1)
            self.parameter.child(device, 'Pixel Size Y').setValue(ai.pixel2)
            self.parameter.child(device, 'Center X').setValue(fit2d['centerX'])
            self.parameter.child(device, 'Center Y').setValue(fit2d['centerY'])
            self.parameter.child(device, 'Detector Distance').setValue(
                fit2d['directDist'] / 1000)
            self.parameter.child('Wavelength').setValue(ai.wavelength)
        finally:
            self.setSilence(False)
        self.simulateCalibrant()

    def setSilence(self, silence):
        if silence:
            self.parameter.sigTreeStateChanged.disconnect(
                self.simulateCalibrant)
            self.parameter.sigTreeStateChanged.disconnect(self.genAIs)
        else:
            self.parameter.sigTreeStateChanged.connect(self.simulateCalibrant)
            self.parameter.sigTreeStateChanged.connect(self.genAIs)

    def addDevice(self, device):
        try:
            self.setSilence(True)
            devicechild = DeviceParameter(device)
            self.parameter.addChild(devicechild)
            ai = AzimuthalIntegrator(wavelength=self.parameter['Wavelength'])
            self.AIs[device] = ai
            self.multiAI.ais = list(self.AIs.values())
        finally:
            self.setSilence(False)

    def setModels(self, headermodel, selectionmodel):
        self.headermodel = headermodel
        self.headermodel.dataChanged.connect(self.dataChanged)
        self.selectionmodel = selectionmodel

    def dataChanged(self, start, end):
        devices = self.headermodel.item(
            self.selectionmodel.currentIndex()).header.devices()
        for device in devices:
            if device not in self.AIs:
                self.addDevice(device)

    def apply(self):
        AI = AzimuthalIntegrator(
            wavelength=self.parameter.child('Wavelength').value())
        # if Calibration.isChecked():
        #     AI.setFit2D(self.getvalue('Detector Distance') * 1000.,
        #                 self.getvalue('Center X'),
        #                 self.getvalue('Center Y'),
        #                 self.getvalue('Detector Tilt'),
        #                 360. - self.getvalue('Detector Rotation'),
        #                 self.getvalue('Pixel Size Y') * 1.e6,
        #                 self.getvalue('Pixel Size X') * 1.e6)
        # elif self.wxdiffstyle.isChecked():
        #     AI.setFit2D(self.getvalue('Detector Distance') * 1000.,
        #                 self.getvalue('Center X'),
        #                 self.getvalue('Center Y'),
        #                 self.getvalue('Detector Tilt') / 2. / np.pi * 360.,
        #                 360. - (2 * np.pi - self.getvalue('Detector Rotation')) / 2. / np.pi * 360.,
        #                 self.getvalue('Pixel Size Y') * 1.e6,
        #                 self.getvalue('Pixel Size X') * 1.e6)
        # AI.set_wavelength(self.getvalue('Wavelength'))
        # # print AI

        activeCalibration = AI

    def save(self):
        self.apply()
        return self.parameter.saveState(filter='user')

    def restore(self, state):
        pass
        # self.parameter.restoreState(state, addChildren=False, removeChildren=False)

    def wavelengthChanged(self):
        self.param('Energy').setValue(1.239842e-6 /
                                      self.param('Wavelength').value(),
                                      blockSignal=self.EnergyChanged)

    def energyChanged(self):
        self.param('Wavelength').setValue(1.239842e-6 /
                                          self.param('Energy').value(),
                                          blockSignal=self.WavelengthChanged)