def _GoniostatRotation_to_python(self,
                                     py4jGoniostatRotation,
                                     isSweepSetting=False):
        if py4jGoniostatRotation is None:
            return None

        uuidString = py4jGoniostatRotation.getId().toString()
        axisSettings = py4jGoniostatRotation.getAxisSettings()
        if isSweepSetting:
            scanAxis = py4jGoniostatRotation.getScanAxis()
            result = GphlMessages.GoniostatSweepSetting(
                id_=uuid.UUID(uuidString), scanAxis=scanAxis, **axisSettings)
        else:
            result = GphlMessages.GoniostatRotation(id_=uuid.UUID(uuidString),
                                                    **axisSettings)

        py4jGoniostatTranslation = py4jGoniostatRotation.getTranslation()
        if py4jGoniostatTranslation:
            translationAxisSettings = py4jGoniostatTranslation.getAxisSettings(
            )
            translationUuidString = py4jGoniostatTranslation.getId().toString()
            # Next line creates Translation and links it to Rotation
            GphlMessages.GoniostatTranslation(
                id_=uuid.UUID(translationUuidString),
                rotation=result,
                **translationAxisSettings)
        return result
Beispiel #2
0
 def _DetectorSetting_to_python(self, py4jDetectorSetting):
     if py4jDetectorSetting is None:
         return None
     uuidString = py4jDetectorSetting.getId().toString()
     axisSettings = py4jDetectorSetting.getAxisSettings()
     #
     return GphlMessages.DetectorSetting(id_=uuid.UUID(uuidString), **axisSettings)
 def _GeometricStrategy_to_python(self, py4jGeometricStrategy):
     uuidString = py4jGeometricStrategy.getId().toString()
     sweeps = frozenset(
         self._Sweep_to_python(x)
         for x in py4jGeometricStrategy.getSweeps())
     beamSetting = py4jGeometricStrategy.getDefaultBeamSetting()
     if beamSetting:
         beamSetting = self._BeamSetting_to_python(beamSetting)
     else:
         beamSetting = None
     detectorSetting = py4jGeometricStrategy.getDefaultDetectorSetting()
     if detectorSetting:
         detectorSetting = self._DetectorSetting_to_python(detectorSetting)
     else:
         detectorSetting = None
     return GphlMessages.GeometricStrategy(
         isInterleaved=py4jGeometricStrategy.isInterleaved(),
         isUserModifiable=py4jGeometricStrategy.isUserModifiable(),
         allowedWidths=py4jGeometricStrategy.getAllowedWidths(),
         defaultWidthIdx=py4jGeometricStrategy.getDefaultWidthIdx(),
         defaultBeamSetting=beamSetting,
         defaultDetectorSetting=detectorSetting,
         sweeps=sweeps,
         id_=uuid.UUID(uuidString),
     )
 def _ScanWidth_to_python(self, py4jScanWidth):
     uuidString = py4jScanWidth.getId().toString()
     return GphlMessages.ScanWidth(
         imageWidth=py4jScanWidth.getImageWidth(),
         numImages=py4jScanWidth.getNumImages(),
         id_=uuid.UUID(uuidString),
     )
 def _ChooseLattice_to_python(self, py4jChooseLattice):
     lattice_format = py4jChooseLattice.getFormat().toString()
     solutions = py4jChooseLattice.getSolutions()
     lattices = py4jChooseLattice.getLattices()
     return GphlMessages.ChooseLattice(lattice_format=lattice_format,
                                       solutions=solutions,
                                       lattices=lattices)
 def _ScanExposure_to_python(self, py4jScanExposure):
     uuidString = py4jScanExposure.getId().toString()
     return GphlMessages.ScanExposure(
         time=py4jScanExposure.getTime(),
         transmission=py4jScanExposure.getTransmission(),
         id_=uuid.UUID(uuidString),
     )
 def _BeamSetting_to_python(self, py4jBeamSetting):
     if py4jBeamSetting is None:
         return None
     uuidString = py4jBeamSetting.getId().toString()
     #
     return GphlMessages.BeamSetting(
         id_=uuid.UUID(uuidString),
         wavelength=py4jBeamSetting.getWavelength())
 def _RequestCentring_to_python(self, py4jRequestCentring):
     goniostatRotation = self._GoniostatRotation_to_python(
         py4jRequestCentring.getGoniostatRotation())
     return GphlMessages.RequestCentring(
         currentSettingNo=py4jRequestCentring.getCurrentSettingNo(),
         totalRotations=py4jRequestCentring.getTotalRotations(),
         goniostatRotation=goniostatRotation,
     )
 def _BeamstopSetting_to_python(self, py4jBeamstopSetting):
     if py4jBeamstopSetting is None:
         return None
     uuidString = py4jBeamstopSetting.getId().toString()
     axisSettings = py4jBeamstopSetting.getAxisSettings()
     #
     return GphlMessages.BeamstopSetting(id=uuid.UUID(uuidString),
                                         **axisSettings)
 def _Scan_to_python(self, py4jScan, sweep):
     uuidString = py4jScan.getId().toString()
     return GphlMessages.Scan(
         width=self._ScanWidth_to_python(py4jScan.getWidth()),
         exposure=self._ScanExposure_to_python(py4jScan.getExposure()),
         imageStartNum=py4jScan.getImageStartNum(),
         start=py4jScan.getStart(),
         sweep=sweep,
         filenameParams=py4jScan.getFilenameParams(),
         id_=uuid.UUID(uuidString),
     )
 def _CollectionProposal_to_python(self, py4jCollectionProposal):
     uuidString = py4jCollectionProposal.getId().toString()
     strategy = self._GeometricStrategy_to_python(
         py4jCollectionProposal.getStrategy())
     id2Sweep = dict((str(x.id), x) for x in strategy.sweeps)
     scans = []
     for py4jScan in py4jCollectionProposal.getScans():
         sweep = id2Sweep[py4jScan.getSweep().getId().toString()]
         scans.append(self._Scan_to_python(py4jScan, sweep))
     return GphlMessages.CollectionProposal(
         relativeImageDir=py4jCollectionProposal.getRelativeImageDir(),
         strategy=strategy,
         scans=scans,
         id=uuid.UUID(uuidString),
     )
Beispiel #12
0
    def _decode_py4j_message(self, py4j_message):
        """Extract messageType and convert py4J object to python object"""

        # Determine message type
        message_type = py4j_message.getPayloadClass().getSimpleName()

        xx0 = py4j_message.getEnactmentId()
        enactment_id = xx0 and xx0.toString()

        xx0 = py4j_message.getCorrelationId()
        correlation_id = xx0 and xx0.toString()
        logging.getLogger("HWR").debug(
            "GPhL incoming: message=%s, jobId=%s,  messageId=%s"
            % (message_type, enactment_id, correlation_id)
        )

        if message_type == "String":
            payload = py4j_message.getPayload()

        else:
            if message_type.endswith("Impl"):
                message_type = message_type[:-4]
            converterName = "_%s_to_python" % message_type

            try:
                # determine converter function
                converter = getattr(self, converterName)
            except AttributeError:
                logging.getLogger("HWR").error(
                    "GPhL Message type %s not recognised (no %s function)"
                    % (message_type, converterName)
                )
                payload = None
            else:
                try:
                    # Convert to Python objects
                    payload = converter(py4j_message.getPayload())
                except NotImplementedError:
                    logging.getLogger("HWR").error(
                        "Processing of GPhL message %s not implemented", message_type
                    )
                    payload = None
        #
        return GphlMessages.ParsedMessage(
            message_type, payload, enactment_id, correlation_id
        )
    def abort_workflow(self, message=None):
        """Abort workflow - may be called from controller in any state"""

        logging.getLogger("HWR").info("Aborting workflow: %s", message)
        logging.getLogger("user_level_log").info("Aborting workflow ...")
        if self._await_result is not None:
            # Workflow waiting for answer - send abort
            self._await_result = [(GphlMessages.BeamlineAbort(), None)]

        # Shut down hardware object
        que = self.workflow_queue
        if que is None:
            self.workflow_ended()
        else:
            # If the queue is running,
            # workflow_ended will be called from post_execute
            que.put_nowait(StopIteration)
    def _Sweep_to_python(self, py4jSweep):

        # NB scans are not set - where scans are present in a message,
        # the link is set from the Scan side.

        uuidString = py4jSweep.getId().toString()
        return GphlMessages.Sweep(
            goniostatSweepSetting=self._GoniostatSweepSetting_to_python(
                py4jSweep.getGoniostatSweepSetting()),
            detectorSetting=self._DetectorSetting_to_python(
                py4jSweep.getDetectorSetting()),
            beamSetting=self._BeamSetting_to_python(
                py4jSweep.getBeamSetting()),
            start=py4jSweep.getStart(),
            width=py4jSweep.getWidth(),
            beamstopSetting=self._BeamstopSetting_to_python(
                py4jSweep.getBeamstopSetting()),
            sweepGroup=py4jSweep.getSweepGroup(),
            id_=uuid.UUID(uuidString),
        )
    def workflow_ended(self):
        if self.get_state() == States.OFF:
            # No workflow to abort
            return

        logging.getLogger("HWR").debug("GPhL workflow ended")
        self.set_state(States.OFF)
        if self._await_result is not None:
            # We are awaiting an answer - give an abort
            self._await_result.append((GphlMessages.BeamlineAbort(), None))
            time.sleep(0.2)
        elif self._running_process is not None:
            self._running_process = None
            # NBNB TODO how do we close down the workflow if there is no answer pending?

        self._enactment_id = None
        self._workflow_name = None
        self.workflow_queue = None
        self._await_result = None

        # xx0 = self._running_process
        # self._running_process = None
        xx0 = self.collect_emulator_process
        if xx0 is not None:
            self.collect_emulator_process = "ABORTED"
            try:
                if xx0.poll() is None:
                    xx0.send_signal(signal.SIGINT)
                    time.sleep(3)
                    if xx0.poll() is None:
                        xx0.terminate()
                        time.sleep(9)
                        if xx0.poll() is None:
                            xx0.kill()
            except Exception:
                logging.getLogger("HWR").info(
                    "Exception while terminating external workflow process %s",
                    xx0)
                logging.getLogger("HWR").info("Error was:", exc_info=True)
 def _SubprocessStopped_to_python(self, py4jSubprocessStopped):
     return GphlMessages.SubprocessStopped()
 def _PrepareForCentring_to_python(self, py4jPrepareForCentring):
     return GphlMessages.PrepareForCentring()
 def _ObtainPriorInformation_to_python(self, py4jObtainPriorInformation):
     return GphlMessages.ObtainPriorInformation()
 def _RequestConfiguration_to_python(self, py4jRequestConfiguration):
     return GphlMessages.RequestConfiguration()
    def processMessage(self, py4j_message):
        """Receive and process message from workflow server
        Return goes to server

        NB Callled freom external java) workflow"""

        xx0 = self._decode_py4j_message(py4j_message)
        message_type = xx0.message_type
        payload = xx0.payload
        correlation_id = xx0.correlation_id
        enactment_id = xx0.enactment_id

        if not enactment_id:
            logging.getLogger("HWR").error(
                "GPhL message lacks enactment ID - sending 'Abort' to external workflow"
            )
            return self._response_to_server(GphlMessages.BeamlineAbort(),
                                            correlation_id)

        elif self._enactment_id is None:
            # NB this should be made less primitive
            # once we are past direct function calls
            self._enactment_id = enactment_id

        elif self._enactment_id != enactment_id:
            logging.getLogger("HWR").error(
                "Workflow enactment ID %s != message enactment ID %s"
                " - sending 'Abort' to external workflow" %
                (self._enactment_id, enactment_id))
            return self._response_to_server(GphlMessages.BeamlineAbort(),
                                            correlation_id)

        elif not payload:
            logging.getLogger("HWR").error(
                "GPhL message lacks payload - sending 'Abort' to external workflow"
            )
            return self._response_to_server(GphlMessages.BeamlineAbort(),
                                            correlation_id)

        if message_type in ("SubprocessStarted", "SubprocessStopped"):

            if self.workflow_queue is not None:
                # Could happen if we have ended the workflow
                self.workflow_queue.put_nowait(
                    (message_type, payload, correlation_id, None))
            logging.getLogger("HWR").debug(
                "Subprocess start/stop - return None")
            return None

        elif message_type in (
                "RequestConfiguration",
                "GeometricStrategy",
                "CollectionProposal",
                "ChooseLattice",
                "RequestCentring",
                "ObtainPriorInformation",
                "PrepareForCentring",
        ):
            # Requests:
            self._await_result = []
            self.set_state(States.OPEN)
            if self.workflow_queue is None:
                # Could be None if we have ended the workflow
                return self._response_to_server(GphlMessages.BeamlineAbort(),
                                                correlation_id)
            else:
                self.workflow_queue.put_nowait(
                    (message_type, payload, correlation_id,
                     self._await_result))
                while not self._await_result:
                    time.sleep(0.1)
                result, correlation_id = self._await_result.pop(0)
                self._await_result = None
                if self.get_state() == States.OPEN:
                    self.set_state(States.RUNNING)

                logging.getLogger("HWR").debug(
                    "GPhL - response=%s jobId=%s messageId=%s" %
                    (result.__class__.__name__, enactment_id, correlation_id))
                return self._response_to_server(result, correlation_id)

        elif message_type in ("WorkflowAborted", "WorkflowCompleted",
                              "WorkflowFailed"):
            if self.workflow_queue is not None:
                # Could happen if we have ended the workflow
                self.workflow_queue.put_nowait(
                    (message_type, payload, correlation_id, None))
                self.workflow_queue.put_nowait(StopIteration)
            logging.getLogger("HWR").debug("Aborting - return None")
            return None

        else:
            logging.getLogger("HWR").error(
                "GPhL Unknown message type: %s - aborting", message_type)
            return self._response_to_server(GphlMessages.BeamlineAbort(),
                                            correlation_id)
    def test_lattice_selection(self):
        """Dummy test of lattice selection UI"""

        # |NB @~@~for test only
        test_payload = GphlMessages.ChooseLattice(
            lattice_format="IDXREF",
            crystalSystem="m",
            lattices=["tP", "aP"],
            solutions="""
*********** DETERMINATION OF LATTICE CHARACTER AND BRAVAIS LATTICE ***********

 The CHARACTER OF A LATTICE is defined by the metrical parameters of its
 reduced cell as described in the INTERNATIONAL TABLES FOR CRYSTALLOGRAPHY
 Volume A, p. 746 (KLUWER ACADEMIC PUBLISHERS, DORDRECHT/BOSTON/LONDON, 1989).
 Note that more than one lattice character may have the same BRAVAIS LATTICE.

 A lattice character is marked "*" to indicate a lattice consistent with the
 observed locations of the diffraction spots. These marked lattices must have
 low values for the QUALITY OF FIT and their implicated UNIT CELL CONSTANTS
 should not violate the ideal values by more than
 MAXIMUM_ALLOWED_CELL_AXIS_RELATIVE_ERROR=  0.03
 MAXIMUM_ALLOWED_CELL_ANGLE_ERROR=           1.5 (Degrees)

  LATTICE-  BRAVAIS-   QUALITY  UNIT CELL CONSTANTS (ANGSTROEM & DEGREES)
 CHARACTER  LATTICE     OF FIT      a      b      c   alpha  beta gamma

 *  44        aP          0.0      56.3   56.3  102.3  90.0  90.0  90.0
 *  31        aP          0.0      56.3   56.3  102.3  90.0  90.0  90.0
 *  33        mP          0.0      56.3   56.3  102.3  90.0  90.0  90.0
 *  35        mP          0.0      56.3   56.3  102.3  90.0  90.0  90.0
 *  34        mP          0.0      56.3  102.3   56.3  90.0  90.0  90.0
 *  32        oP          0.0      56.3   56.3  102.3  90.0  90.0  90.0
 *  14        mC          0.1      79.6   79.6  102.3  90.0  90.0  90.0
 *  10        mC          0.1      79.6   79.6  102.3  90.0  90.0  90.0
 *  13        oC          0.1      79.6   79.6  102.3  90.0  90.0  90.0
 *  11        tP          0.1      56.3   56.3  102.3  90.0  90.0  90.0
    37        mC        250.0     212.2   56.3   56.3  90.0  90.0  74.6
    36        oC        250.0      56.3  212.2   56.3  90.0  90.0 105.4
    28        mC        250.0      56.3  212.2   56.3  90.0  90.0  74.6
    29        mC        250.0      56.3  125.8  102.3  90.0  90.0  63.4
    41        mC        250.0     212.3   56.3   56.3  90.0  90.0  74.6
    40        oC        250.0      56.3  212.2   56.3  90.0  90.0 105.4
    39        mC        250.0     125.8   56.3  102.3  90.0  90.0  63.4
    30        mC        250.0      56.3  212.2   56.3  90.0  90.0  74.6
    38        oC        250.0      56.3  125.8  102.3  90.0  90.0 116.6
    12        hP        250.1      56.3   56.3  102.3  90.0  90.0  90.0
    27        mC        500.0     125.8   56.3  116.8  90.0 115.5  63.4
    42        oI        500.0      56.3   56.3  219.6 104.8 104.8  90.0
    15        tI        500.0      56.3   56.3  219.6  75.2  75.2  90.0
    26        oF        625.0      56.3  125.8  212.2  83.2 105.4 116.6
     9        hR        750.0      56.3   79.6  317.1  90.0 100.2 135.0
     1        cF        999.0     129.6  129.6  129.6 128.6  75.7 128.6
     2        hR        999.0      79.6  116.8  129.6 118.9  90.0 109.9
     3        cP        999.0      56.3   56.3  102.3  90.0  90.0  90.0
     5        cI        999.0     116.8   79.6  116.8  70.1  39.8  70.1
     4        hR        999.0      79.6  116.8  129.6 118.9  90.0 109.9
     6        tI        999.0     116.8  116.8   79.6  70.1  70.1  39.8
     7        tI        999.0     116.8   79.6  116.8  70.1  39.8  70.1
     8        oI        999.0      79.6  116.8  116.8  39.8  70.1  70.1
    16        oF        999.0      79.6   79.6  219.6  90.0 111.2  90.0
    17        mC        999.0      79.6   79.6  116.8  70.1 109.9  90.0
    18        tI        999.0     116.8  129.6   56.3  64.3  90.0 118.9
    19        oI        999.0      56.3  116.8  129.6  61.1  64.3  90.0
    20        mC        999.0     116.8  116.8   56.3  90.0  90.0 122.4
    21        tP        999.0      56.3  102.3   56.3  90.0  90.0  90.0
    22        hP        999.0      56.3  102.3   56.3  90.0  90.0  90.0
    23        oC        999.0     116.8  116.8   56.3  90.0  90.0  57.6
    24        hR        999.0     162.2  116.8   56.3  90.0  69.7  77.4
    25        mC        999.0     116.8  116.8   56.3  90.0  90.0  57.6
    43        mI        999.0      79.6  219.6   56.3 104.8 135.0  68.8

 For protein crystals the possible space group numbers corresponding  to""",
        )
        if self.workflow_queue is not None:
            # Could happen if we have ended the workflow
            self.workflow_queue.put_nowait(
                ("ChooseLattice", test_payload, "9999999", None))
 def _SubprocessStarted_to_python(self, py4jSubprocessStarted):
     return GphlMessages.SubprocessStarted(
         name=py4jSubprocessStarted.getName())