def _run_edna(self, input_file, results_file, process_directory): """Starts EDNA""" msg = "Starting EDNA characterisation using xml file %s" % input_file logging.getLogger("queue_exec").info(msg) args = (self.start_edna_command, input_file, results_file, process_directory) subprocess.call("%s %s %s %s" % args, shell=True) self.result = None if os.path.exists(results_file): self.result = XSDataResultMXCuBE.parseFile(results_file) return self.result
def preProcess(self, _edPlugin=None): """ This method prepares the input for the CCP4i plugin and loads it. """ EDPluginControl.preProcess(self, _edPlugin) self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.preProcess...") self.tStart = time.time() # self.edPluginExecOutputHTML = self.loadPlugin(self.strPluginExecOutputHTMLName, "OutputHTML") self.edPluginExecSimpleHTML = self.loadPlugin(self.strPluginExecSimpleHTMLName, "SimpleHTML") self.edPluginISPyBRetrieveDataCollection = self.loadPlugin(self.strPluginISPyBRetrieveDataCollection, \ "ISPyBRetrieveDataCollection") self.xsDataResultMXCuBE = XSDataResultMXCuBE()
class EDPluginControlInterfaceToMXCuBEv1_4(EDPluginControl): """ This is the plugin interface to launch the MXv1 characterisation from an MXCuBE gui. It is for the moment a wrapper for the EDPluginControlCCP4iv1_1 plugin, which also runs the ISPyB control plugin if a data collection id is available. """ EDNA_CONTACT_EMAIL = "contactEmail" EDNA_EMAIL_SENDER = "emailSender" def __init__(self): """ Initialisation of EDPluginControlInterfaceToMXCuBEv1_4: - Input data type class : XSDataInputMXCuBE - Name of default characterisation plugin : EDPluginControlCharacterisationv1_1 """ EDPluginControl.__init__(self) self.setXSDataInputClass(XSDataInputMXCuBE) self.strPluginControlInterface = "EDPluginControlInterfacev1_2" self.edPluginControlInterface = None self.strPluginControlISPyB = "EDPluginControlISPyBv1_4" self.edPluginControlISPyB = None self.xsDataResultMXCuBE = None self.xsDataIntegerDataCollectionId = None self.strPluginExecOutputHTMLName = "EDPluginExecOutputHTMLv1_0" self.edPluginExecOutputHTML = None self.strPluginExecSimpleHTMLName = "EDPluginExecSimpleHTMLPagev1_1" self.edPluginExecSimpleHTML = None self.strPluginISPyBRetrieveDataCollection = "EDPluginISPyBRetrieveDataCollectionv1_4" self.edPluginISPyBRetrieveDataCollection = None self.strPluginControlH5ToCBF = "EDPluginControlH5ToCBFv1_1" self.edPluginControlH5ToCBF = None self.strPluginStoreWorkflow = "EDPluginISPyBStoreWorkflowv1_4" self.edPluginStoreWorkflow = None self.strPluginStoreWorkflowStep = "EDPluginISPyBStoreWorkflowStepv1_4" self.edPluginStoreWorkflowStep = None self.strUpdateDataCollectionGroupWorkflowId = "EDPluginISPyBUpdateDataCollectionGroupWorkflowIdv1_4" self.edPluginUpdateDataCollectionGroupWorkflowId = None self.strEDNAContactEmail = None self.strEDNAEmailSender = "*****@*****.**" self.tStart = None self.tStop = None self.fFluxThreshold = 1e3 self.bIsEigerDetector = False self.xsDataFirstImage = None def checkParameters(self): """ Checks the mandatory input parameters : - dataSet - outputFileDirectory """ self.verboseDebug("EDPluginControlInterfaceToMXCuBEv1_4.checkParameters") self.checkMandatoryParameters(self.getDataInput(), "Data Input is None") self.checkMandatoryParameters(self.getDataInput().getDataSet(), "dataSet") def configure(self): EDPluginControl.configure(self) self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.configure") self.strEDNAEmailSender = self.config.get(self.EDNA_EMAIL_SENDER, self.strEDNAEmailSender) self.strEDNAContactEmail = self.config.get(self.EDNA_CONTACT_EMAIL, self.strEDNAContactEmail) def preProcess(self, _edPlugin=None): """ This method prepares the input for the CCP4i plugin and loads it. """ EDPluginControl.preProcess(self, _edPlugin) self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.preProcess...") self.tStart = time.time() # self.edPluginExecOutputHTML = self.loadPlugin(self.strPluginExecOutputHTMLName, "OutputHTML") self.edPluginExecSimpleHTML = self.loadPlugin(self.strPluginExecSimpleHTMLName, "SimpleHTML") self.edPluginISPyBRetrieveDataCollection = self.loadPlugin( self.strPluginISPyBRetrieveDataCollection, "ISPyBRetrieveDataCollection" ) self.xsDataResultMXCuBE = XSDataResultMXCuBE() def process(self, _edPlugin=None): EDPluginControl.process(self, _edPlugin) self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.process...") xsDataInputMXCuBE = self.getDataInput() xsDataInputInterface = XSDataInputInterface() self.edPluginControlInterface = self.loadPlugin(self.strPluginControlInterface) self.xsDataFirstImage = None for xsDataSetMXCuBE in xsDataInputMXCuBE.getDataSet(): for xsDataFile in xsDataSetMXCuBE.getImageFile(): if xsDataFile.path.value.endswith(".h5"): self.bIsEigerDetector = True self.xsDataFirstImage = xsDataFile xsDataInputControlH5ToCBF = XSDataInputControlH5ToCBF() xsDataInputControlH5ToCBF.hdf5File = XSDataFile(xsDataFile.path) xsDataInputControlH5ToCBF.imageNumber = XSDataInteger( EDUtilsImage.getImageNumber(xsDataFile.path.value) ) edPluginControlH5ToCBF = self.loadPlugin(self.strPluginControlH5ToCBF, "ControlH5ToCBF") edPluginControlH5ToCBF.dataInput = xsDataInputControlH5ToCBF edPluginControlH5ToCBF.executeSynchronous() cbfFile = edPluginControlH5ToCBF.dataOutput.outputCBFFile xsDataInputInterface.addImagePath(cbfFile) else: xsDataInputInterface.addImagePath(xsDataFile) if self.xsDataFirstImage is None: self.xsDataFirstImage = xsDataFile xsDataExperimentalCondition = self.getFluxAndBeamSizeFromISPyB( self.xsDataFirstImage, xsDataInputMXCuBE.getExperimentalCondition() ) xsDataInputInterface.setExperimentalCondition(xsDataExperimentalCondition) xsDataInputInterface.setDiffractionPlan(xsDataInputMXCuBE.getDiffractionPlan()) xsDataInputInterface.setSample(xsDataInputMXCuBE.getSample()) xsDataInputInterface.setDataCollectionId(xsDataInputMXCuBE.getDataCollectionId()) self.edPluginControlInterface.setDataInput(xsDataInputInterface) if self.edPluginControlInterface is not None: self.connectProcess(self.edPluginControlInterface.executeSynchronous) self.edPluginControlInterface.connectSUCCESS(self.doSuccessActionInterface) self.edPluginControlInterface.connectFAILURE(self.doFailureActionInterface) def finallyProcess(self, _edPlugin=None): EDPluginControl.finallyProcess(self, _edPlugin) self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.postProcess...") self.setDataOutput(self.xsDataResultMXCuBE) def doSuccessActionInterface(self, _edPlugin=None): self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.doSuccessActionInterface...") self.retrieveSuccessMessages( self.edPluginControlInterface, "EDPluginControlInterfaceToMXCuBEv1_4.doSuccessActionInterface" ) # Send success email message (MXSUP-183): self.tStop = time.time() strSubject = "SUCCESS" strMessage = "Characterisation success!" self.storeResultsInISPyB(strSubject, strMessage) def doFailureActionInterface(self, _edPlugin=None): self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.doFailureActionInterface...") # Send failure email message (MXSUP-183): self.tStop = time.time() strSubject = "FAILURE" strMessage = "Characterisation FAILURE!" self.storeResultsInISPyB(strSubject, strMessage) # self.setFailure() # xsDataResultCharacterisation = None # if self.edPluginControlInterface.hasDataOutput("characterisation"): # xsDataResultCharacterisation = self.edPluginControlInterface.getDataOutput("characterisation")[0] # # Execute plugin which creates a simple HTML page # self.executeSimpleHTML(xsDataResultCharacterisation) # xsDataResultCharacterisation = self.edPluginControlInterface.dataOutput.resultCharacterisation # if xsDataResultCharacterisation is not None: # self.xsDataResultMXCuBE.characterisationResult = xsDataResultCharacterisation # if xsDataResultCharacterisation.getStatusMessage(): # strMessage += "\n\n" # strMessage += xsDataResultCharacterisation.getStatusMessage().getValue() # if xsDataResultCharacterisation.getShortSummary(): # strMessage += "\n\n" # strMessage += xsDataResultCharacterisation.getShortSummary().getValue() # self.sendEmail(strSubject, strMessage) def storeResultsInISPyB(self, _strSubject, _strMessage): strSubject = _strSubject strMessage = _strMessage xsDataResultCharacterisation = self.edPluginControlInterface.getDataOutput().getResultCharacterisation() if self.bIsEigerDetector: xsDataResultCharacterisation = self.makeNumberOfImagesMultipleOf100(xsDataResultCharacterisation) self.xsDataResultMXCuBE.setCharacterisationResult(xsDataResultCharacterisation) xsDataResultControlISPyB = self.edPluginControlInterface.getDataOutput().getResultControlISPyB() if xsDataResultControlISPyB != None: self.xsDataResultMXCuBE.setScreeningId(xsDataResultControlISPyB.getScreeningId()) if xsDataResultCharacterisation != None: self.xsDataResultMXCuBE.characterisationResult = xsDataResultCharacterisation strPathCharacterisationResult = os.path.join(self.getWorkingDirectory(), "CharacterisationResult.xml") xsDataResultCharacterisation.exportToFile(strPathCharacterisationResult) self.xsDataResultMXCuBE.setListOfOutputFiles(XSDataString(strPathCharacterisationResult)) # For the moment, create "DNA" style output directory strPathToDNAFileDirectory = self.createDNAFileDirectoryPath(xsDataResultCharacterisation) xsDataDictionaryLogFile = None if self.createDNAFileDirectory(strPathToDNAFileDirectory): xsDataDictionaryLogFile = self.createOutputFileDictionary( xsDataResultCharacterisation, strPathToDNAFileDirectory ) strPyArchPathToDNAFileDirectory = EDHandlerESRFPyarchv1_0.createPyarchFilePath(strPathToDNAFileDirectory) if self.createDNAFileDirectory(strPyArchPathToDNAFileDirectory): xsDataDictionaryLogFile = self.createOutputFileDictionary( xsDataResultCharacterisation, strPyArchPathToDNAFileDirectory ) self.xsDataResultMXCuBE.setOutputFileDictionary(xsDataDictionaryLogFile) if xsDataResultCharacterisation.getStatusMessage(): strMessage += "\n\n" strMessage += xsDataResultCharacterisation.getStatusMessage().getValue() if xsDataResultCharacterisation.getShortSummary(): strMessage += "\n\n" strMessage += xsDataResultCharacterisation.getShortSummary().getValue() self.sendEmail(strSubject, strMessage) # Fix for bug EDNA-55 : If burning strategy EDNA2html shouldn't be run bRunExecOutputHTML = False xsDataInputMXCuBE = self.getDataInput() xsDataDiffractionPlan = xsDataInputMXCuBE.getDiffractionPlan() if xsDataDiffractionPlan is not None and xsDataDiffractionPlan.getStrategyOption() is not None: strStrategyOption = xsDataDiffractionPlan.getStrategyOption().getValue() if strStrategyOption.find("-DamPar") != -1: bRunExecOutputHTML = False if (self.edPluginExecOutputHTML is not None) and bRunExecOutputHTML: self.edPluginExecOutputHTML.setDataInput( XSDataFile(XSDataString(strPathToDNAFileDirectory)), "dnaFileDirectory" ) self.edPluginExecOutputHTML.execute() # Fix for bug MXSUP-251: Put the BEST .par file in the EDNA characterisation root directory xsDataIntegrationResult = xsDataResultCharacterisation.getIntegrationResult() if xsDataIntegrationResult: listXSDataIntegrationSubWedgeResult = xsDataIntegrationResult.getIntegrationSubWedgeResult() for xsDataIntegrationSubWedgeResult in listXSDataIntegrationSubWedgeResult: if xsDataIntegrationSubWedgeResult.getBestfilePar() is not None: strBestfilePar = xsDataIntegrationSubWedgeResult.getBestfilePar().getValue() # Put the file one directory above the mxCuBE v1.3 plugin working directory: strDir = os.path.dirname(self.getWorkingDirectory()) strPath = os.path.join(strDir, "bestfile.par") EDUtilsFile.writeFile(strPath, strBestfilePar) break # Execute plugin which creates a simple HTML page self.executeSimpleHTML(xsDataResultCharacterisation) # Upload the best wilson plot path to ISPyB strBestWilsonPlotPath = EDHandlerXSDataISPyBv1_4.getBestWilsonPlotPath(xsDataResultCharacterisation) strBestWilsonPlotPyarchPath = None if strBestWilsonPlotPath is not None and strPyArchPathToDNAFileDirectory is not None: # Copy wilson path to Pyarch strBestWilsonPlotPyarchPath = os.path.join( strPyArchPathToDNAFileDirectory, os.path.basename(strBestWilsonPlotPath) ) if not os.path.exists(strBestWilsonPlotPyarchPath): if not os.path.exists(os.path.dirname(strBestWilsonPlotPyarchPath)): os.makedirs(os.path.dirname(strBestWilsonPlotPyarchPath), 755) shutil.copy(strBestWilsonPlotPath, strBestWilsonPlotPyarchPath) self.DEBUG("Best wilson pyarch path: %s " % strBestWilsonPlotPyarchPath) if self.edPluginControlInterface.dataOutput.resultControlISPyB is not None: xsDataInputISPyBSetBestWilsonPlotPath = XSDataInputISPyBSetBestWilsonPlotPath() xsDataInputISPyBSetBestWilsonPlotPath.dataCollectionId = ( self.edPluginControlInterface.dataOutput.resultControlISPyB.dataCollectionId ) xsDataInputISPyBSetBestWilsonPlotPath.bestWilsonPlotPath = XSDataString(strBestWilsonPlotPyarchPath) edPluginSetBestWilsonPlotPath = self.loadPlugin( "EDPluginISPyBSetBestWilsonPlotPathv1_4", "ISPyBSetBestWilsonPlotPath" ) edPluginSetBestWilsonPlotPath.dataInput = xsDataInputISPyBSetBestWilsonPlotPath edPluginSetBestWilsonPlotPath.executeSynchronous() # Only for the ESRF: if EDUtilsPath.isESRF(): # For EXI: create workflow entry with one workflow step self.edPluginStoreWorkflow = self.loadPlugin(self.strPluginStoreWorkflow) self.edPluginStoreWorkflowStep = self.loadPlugin(self.strPluginStoreWorkflowStep) self.edPluginUpdateDataCollectionGroupWorkflowId = self.loadPlugin( self.strUpdateDataCollectionGroupWorkflowId ) xsDataISPyBWorkflow = XSDataISPyBWorkflow() xsDataISPyBWorkflow.workflowType = XSDataString("Characterisation") xsDataISPyBWorkflow.workflowTitle = XSDataString("Characterisation") xsDataInputISPyBStoreWorkflow = XSDataInputISPyBStoreWorkflow() xsDataInputISPyBStoreWorkflow.workflow = xsDataISPyBWorkflow self.edPluginStoreWorkflow.dataInput = xsDataInputISPyBStoreWorkflow self.edPluginStoreWorkflow.executeSynchronous() if ( self.edPluginStoreWorkflow.dataOutput is not None and self.edPluginStoreWorkflow.dataOutput.workflowId is not None ): workflowId = self.edPluginStoreWorkflow.dataOutput.workflowId.value # Update data collection group xsDataInputISPyBUpdateDataCollectionGroupWorkflowId = ( XSDataInputISPyBUpdateDataCollectionGroupWorkflowId() ) xsDataInputISPyBUpdateDataCollectionGroupWorkflowId.workflowId = XSDataInteger(workflowId) xsDataInputISPyBUpdateDataCollectionGroupWorkflowId.fileLocation = XSDataString( os.path.dirname(self.xsDataFirstImage.path.value) ) xsDataInputISPyBUpdateDataCollectionGroupWorkflowId.fileName = XSDataString( os.path.basename(self.xsDataFirstImage.path.value) ) self.edPluginUpdateDataCollectionGroupWorkflowId.dataInput = ( xsDataInputISPyBUpdateDataCollectionGroupWorkflowId ) self.edPluginUpdateDataCollectionGroupWorkflowId.executeSynchronous() xsDataInputISPyBStoreWorkflowStep = XSDataInputISPyBStoreWorkflowStep() xsDataInputISPyBStoreWorkflowStep.workflowId = XSDataInteger(workflowId) xsDataInputISPyBStoreWorkflowStep.workflowStepType = XSDataString("Characterisation") xsDataInputISPyBStoreWorkflowStep.status = XSDataString("Success") if strBestWilsonPlotPyarchPath is not None: xsDataInputISPyBStoreWorkflowStep.imageResultFilePath = XSDataString( strBestWilsonPlotPyarchPath ) xsDataInputISPyBStoreWorkflowStep.htmlResultFilePath = XSDataString(strPyArchPathToDNAFileDirectory) if self.edPluginExecSimpleHTML.dataOutput is not None: strResultFilePath = self.edPluginExecSimpleHTML.dataOutput.pathToJsonFile.path.value # strPyarchResultFilePath = EDHandlerESRFPyarchv1_0.createPyarchFilePath(strResultFilePath) xsDataInputISPyBStoreWorkflowStep.resultFilePath = XSDataString(strResultFilePath) self.edPluginStoreWorkflowStep.dataInput = xsDataInputISPyBStoreWorkflowStep self.edPluginStoreWorkflowStep.executeSynchronous() def doSuccessActionISPyB(self, _edPlugin): self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.doSuccessActionISPyB...") self.retrieveSuccessMessages( self.edPluginControlISPyB, "EDPluginControlInterfaceToMXCuBEv1_4.doSuccessActionISPyB" ) def doFailureActionISPyB(self, _edPlugin=None): self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.doFailureActionISpyB...") self.retrieveFailureMessages( self.edPluginControlISPyB, "EDPluginControlInterfaceToMXCuBEv1_4.doFailureActionISpyB" ) # Send failure email message (MXSUP-183): strSubject = "%s : FAILURE!" % EDUtilsPath.getEdnaSite() strMessage = "ISPyB FAILURE!" self.sendEmail(strSubject, strMessage) def createDNAFileDirectoryPath(self, _xsDataResultCharacterisation): """ This method creates a "DNA" style directory path, i.e. in the same directory were the images are located a new directory is created with the following convention: dnafiles_prefix_runNumber The path to this directory is returned if the directory was successfully created. """ # First extract all reference image directory paths and names xsDataCollection = _xsDataResultCharacterisation.getDataCollection() listImageDirectoryPath = [] listImagePrefix = [] for xsDataSubWedge in xsDataCollection.getSubWedge(): for xsDataImage in xsDataSubWedge.getImage(): strImagePath = xsDataImage.getPath().getValue() listImageDirectoryPath.append(os.path.dirname(strImagePath)) listImagePrefix.append(EDUtilsImage.getPrefix(strImagePath)) # TODO: Check that all paths and prefixes are the same strImageDirectory = listImageDirectoryPath[0] strPrefix = listImagePrefix[0] # Remove any "ref-" or "postref-" from the prefix in order to make it fully # compatitble with DNA standards: if strPrefix is not None: if strPrefix.startswith("ref-"): strPrefix = strPrefix[4:] elif strPrefix.startswith("postref-"): strPrefix = strPrefix[8:] strDNAFileDirectoryPath = os.path.join(strImageDirectory, "%s_dnafiles" % strPrefix) return strDNAFileDirectoryPath def createDNAFileDirectory(self, _strDNAFileDirectoryPath): """ Create a "DNA-files" directory - if possible. """ bSuccess = False if _strDNAFileDirectoryPath is not None: if os.path.exists(_strDNAFileDirectoryPath): self.warning("Removing existing DNA files directory: %s" % _strDNAFileDirectoryPath) if os.access(_strDNAFileDirectoryPath, os.W_OK): shutil.rmtree(_strDNAFileDirectoryPath) else: self.warning("Cannot remove existing DNA files directory!") if _strDNAFileDirectoryPath is not None: # Check if directory one level up is writeable strDNAFileBaseDirectory = os.path.split(_strDNAFileDirectoryPath)[0] if os.access(strDNAFileBaseDirectory, os.W_OK): self.DEBUG("Creating DNA files directory: %s" % _strDNAFileDirectoryPath) os.makedirs(_strDNAFileDirectoryPath, mode=0o755) bSuccess = True else: self.warning("Cannot create DNA files directory: %s" % _strDNAFileDirectoryPath) return bSuccess def splitHeadDirectory(self, _strPath): """ This method works like os.path.split except that it splits the head directory from the rest of the path. Example: "/" -> [ None, None] "/data" -> ["data", None] "/data/visitor" -> ["data", "visitor"] "/data/visitor/mx415/id14eh2/20100212" -> ["data", "visitor/mx415/id14eh2/20100212"] """ listOfDirectories = _strPath.split(os.sep) strTail = None strHead = None if len(listOfDirectories) > 1: strHead = listOfDirectories[1] if strHead == "": strHead = None if len(listOfDirectories) > 1: for strEntry in listOfDirectories[2:]: if strTail is None: strTail = strEntry else: strTail = os.path.join(strTail, strEntry) return [strHead, strTail] def createOutputFileDictionary(self, _xsDataResultCharacterisation, _strPathToLogFileDirectory=None): """ This method creates an XSDataDictionary containing the name and locations of the characterisation output files. """ xsDataDictionaryLogFile = XSDataDictionary() # Start with the prediction images xsDataIndexingResult = _xsDataResultCharacterisation.getIndexingResult() if xsDataIndexingResult is not None: xsDataGeneratePredictionResult = xsDataIndexingResult.getPredictionResult() if xsDataGeneratePredictionResult is not None: listXSDataImagePrediction = xsDataGeneratePredictionResult.getPredictionImage() for xsDataImagePrediction in listXSDataImagePrediction: xsDataKeyValuePair = XSDataKeyValuePair() iPredictionImageNumber = xsDataImagePrediction.getNumber().getValue() xsDataStringKey = XSDataString("predictionImage_%d" % iPredictionImageNumber) xsDataStringValue = None strPredictionImagePath = xsDataImagePrediction.getPath().getValue() if _strPathToLogFileDirectory is not None: strPredictionImageFileName = EDUtilsFile.getBaseName(strPredictionImagePath) strNewPredictionImagePath = os.path.join(_strPathToLogFileDirectory, strPredictionImageFileName) EDUtilsFile.copyFile(strPredictionImagePath, strNewPredictionImagePath) xsDataStringValue = XSDataString(strNewPredictionImagePath) else: xsDataStringValue = XSDataString(strPredictionImageFileName) xsDataKeyValuePair.setKey(xsDataStringKey) xsDataKeyValuePair.setValue(xsDataStringValue) xsDataDictionaryLogFile.addKeyValuePair(xsDataKeyValuePair) # Best log file strPathToBESTLogFile = None strPathToExecutiveSummary = None if _xsDataResultCharacterisation.getStrategyResult() is not None: if _xsDataResultCharacterisation.getStrategyResult().getBestLogFile() != None: strPathToBESTLogFile = ( _xsDataResultCharacterisation.getStrategyResult().getBestLogFile().getPath().getValue() ) if strPathToBESTLogFile is not None: xsDataStringKey = XSDataString("logFileBest") xsDataStringValue = None if _strPathToLogFileDirectory is not None: strNewBestLogPath = os.path.join(_strPathToLogFileDirectory, "best.log") EDUtilsFile.copyFile(strPathToBESTLogFile, strNewBestLogPath) xsDataStringValue = XSDataString(strNewBestLogPath) else: xsDataStringValue = XSDataString(strPathToBESTLogFile) xsDataKeyValuePair = XSDataKeyValuePair() xsDataKeyValuePair.setKey(xsDataStringKey) xsDataKeyValuePair.setValue(xsDataStringValue) xsDataDictionaryLogFile.addKeyValuePair(xsDataKeyValuePair) if strPathToExecutiveSummary is not None: xsDataStringKey = XSDataString("executiveSummary") xsDataStringValue = None if _strPathToLogFileDirectory is not None: strExecutiveSummaryFileName = EDUtilsFile.getBaseName(strPathToExecutiveSummary) strNewExecutiveSummaryPath = os.path.join(_strPathToLogFileDirectory, strExecutiveSummaryFileName) EDUtilsFile.copyFile(strPathToExecutiveSummary, strNewExecutiveSummaryPath) xsDataStringValue = XSDataString(strNewExecutiveSummaryPath) # Copy also the executive summary file to "dna_log.txt"... strNewExecutiveSummaryPath = os.path.join(_strPathToLogFileDirectory, "dna_log.txt") EDUtilsFile.copyFile(strPathToExecutiveSummary, strNewExecutiveSummaryPath) else: xsDataStringValue = XSDataString(strPathToExecutiveSummary) xsDataKeyValuePair = XSDataKeyValuePair() xsDataKeyValuePair.setKey(xsDataStringKey) xsDataKeyValuePair.setValue(xsDataStringValue) xsDataDictionaryLogFile.addKeyValuePair(xsDataKeyValuePair) return xsDataDictionaryLogFile def doFailureActionCharacterisation(self, _edPlugin=None): """ retrieve the potential warning messages retrieve the potential error messages """ self.DEBUG("EDPluginControlInterfacev1_4.doFailureActionCharacterisation") self.setFailure() # Send failure email message (MXSUP-183): strSubject = "%s : FAILURE!" % EDUtilsPath.getEdnaSite() strMessage = "Characterisation FAILURE!" self.sendEmail(strSubject, strMessage) def getFluxAndBeamSizeFromISPyB(self, _xsDataFirstImage, _xsDataExperimentalCondition): """ This method retrieves the flux and beamsize from ISPyB """ xsDataExperimentalCondition = None if _xsDataExperimentalCondition is not None: bFoundValidFlux = False xsDataExperimentalCondition = _xsDataExperimentalCondition.copy() xsDataInputRetrieveDataCollection = XSDataInputRetrieveDataCollection() xsDataInputRetrieveDataCollection.setImage(XSDataImage(_xsDataFirstImage.getPath())) self.edPluginISPyBRetrieveDataCollection.setDataInput(xsDataInputRetrieveDataCollection) self.edPluginISPyBRetrieveDataCollection.executeSynchronous() xsDataResultRetrieveDataCollection = self.edPluginISPyBRetrieveDataCollection.getDataOutput() if xsDataResultRetrieveDataCollection is not None: xsDataISPyBDataCollection = xsDataResultRetrieveDataCollection.getDataCollection() if xsDataISPyBDataCollection is not None: fFlux = xsDataISPyBDataCollection.getFlux_end() if fFlux is not None: self.screen("ISPyB reports flux to be: %g photons/sec" % fFlux) if fFlux > self.fFluxThreshold: xsDataExperimentalCondition.getBeam().setFlux(XSDataFlux(fFlux)) bFoundValidFlux = True fBeamSizeAtSampleX = xsDataISPyBDataCollection.beamSizeAtSampleX fBeamSizeAtSampleY = xsDataISPyBDataCollection.beamSizeAtSampleY if fBeamSizeAtSampleX is not None and fBeamSizeAtSampleY is not None: self.screen("ISPyB reports beamsize X to be: %.3f mm" % fBeamSizeAtSampleX) self.screen("ISPyB reports beamsize Y to be: %.3f mm" % fBeamSizeAtSampleY) xsDataSize = XSDataSize() xsDataSize.x = XSDataLength(fBeamSizeAtSampleX) xsDataSize.y = XSDataLength(fBeamSizeAtSampleY) xsDataExperimentalCondition.getBeam().setSize(xsDataSize) # Get transmission if it's not already there if xsDataExperimentalCondition.beam.transmission is None: fTransmission = xsDataISPyBDataCollection.transmission xsDataExperimentalCondition.beam.transmission = XSDataDouble(fTransmission) if not bFoundValidFlux: self.screen("No valid flux could be retrieved from ISPyB! Trying to obtain flux from input data.") xsDataBeam = xsDataExperimentalCondition.getBeam() xsDataBeamFlux = xsDataBeam.getFlux() if xsDataBeamFlux is not None: fFluxMXCuBE = xsDataBeamFlux.getValue() self.screen("MXCuBE reports flux to be: %g photons/sec" % fFluxMXCuBE) if fFluxMXCuBE < self.fFluxThreshold: self.screen("MXCuBE flux lower than threshold flux %g photons/s!" % self.fFluxThreshold) self.screen("Forcing flux to 0.0 photons/s") xsDataExperimentalCondition.getBeam().setFlux(XSDataFlux(0.0)) else: # Force missing flux to 0.0 self.screen("No flux neither in ISPyB nor in mxCuBE, forcing flux to 0.0 photon/s") xsDataExperimentalCondition.getBeam().setFlux(XSDataFlux(0.0)) return xsDataExperimentalCondition def updateDataInputCharacterisation(self, _xsDataInputCharacterisation): """ This method updates the xsDataInputCharacterisation object given as argument with the following parameters (if available) goven as input: - Diffraction plan - Beam size - Beam flux - Min exposure time per image - Max oscillation speed - Min oscillation width - Sample information """ self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.createDataInputCharacterisationFromDataSets") xsDataCollection = _xsDataInputCharacterisation.getDataCollection() if _xsDataInputCharacterisation is not None: xsDataInputCCP4i = self.getDataInput() # Update with diffraction plan xsDiffactionPlan = xsDataInputCCP4i.getDiffractionPlan() if xsDiffactionPlan is not None: xsDataCollection.setDiffractionPlan(xsDiffactionPlan) # Update the data collection subwedges with additional experimental conditions for xsDataSubWedge in xsDataCollection.getSubWedge(): xsDataExperimentalCondition = xsDataInputCCP4i.getExperimentalCondition() if xsDataExperimentalCondition is not None: xsDataBeam = xsDataExperimentalCondition.getBeam() if xsDataBeam is not None: xsDataBeamSize = xsDataBeam.getSize() if xsDataBeamSize is not None: xsDataSubWedge.getExperimentalCondition().getBeam().setSize(xsDataBeamSize) xsDataBeamFlux = xsDataBeam.getFlux() if xsDataBeamFlux is not None: xsDataSubWedge.getExperimentalCondition().getBeam().setFlux(xsDataBeamFlux) xsDataMinExposureTime = xsDataBeam.getMinExposureTimePerImage() if xsDataMinExposureTime is not None: xsDataSubWedge.getExperimentalCondition().getBeam().setMinExposureTimePerImage( xsDataMinExposureTime ) xsDataGoniostat = xsDataExperimentalCondition.getGoniostat() if xsDataGoniostat is not None: xsDataMaxOscSpeed = xsDataGoniostat.getMaxOscillationSpeed() if xsDataMaxOscSpeed is not None: xsDataSubWedge.getExperimentalCondition().getGoniostat().setMaxOscillationSpeed( xsDataMaxOscSpeed ) xsDataMinOscWidth = xsDataGoniostat.getMinOscillationWidth() if xsDataMinOscWidth is not None: xsDataSubWedge.getExperimentalCondition().getGoniostat().setMinOscillationWidth( xsDataMinOscWidth ) # Update with the sample xsDataSample = xsDataInputCCP4i.getSample() if xsDataSample is not None: xsDataCollection.setSample(xsDataSample) def getBeamlineProposalFromPath(self, _strPathToImage): """ESRF specific code for extracting the beamline name and prefix from the path""" listPath = _strPathToImage.split("/") strPrefix = EDUtilsImage.getPrefix(_strPathToImage).replace("ref-", "") if listPath[2] == "visitor": strBeamline = listPath[4] strProposal = listPath[3] elif listPath[3] == "inhouse": strBeamline = listPath[2] strProposal = listPath[4] else: strBeamline = "nobeamline" strProposal = "noproposal" return (strBeamline, strProposal, strPrefix) def sendEmail(self, _strSubject, _strMessage): """Sends an email to the EDNA contact person (if configured).""" strTime = "%.1f s" % (self.tStop - self.tStart) if EDUtilsPath.isESRF(): strPathImage = None for dataSet in self.dataInput.dataSet: for imageFile in dataSet.imageFile: strPathImage = imageFile.path.value break if strPathImage is not None: (strBeamline, strProposal, strPrefix) = self.getBeamlineProposalFromPath(strPathImage) else: strBeamline = "Unknown" strProposal = "Unknown" strPrefix = "Unknown" strHost = socket.gethostname() strSubject = "EDNA ch %s %s %s %s %s (%s)" % ( _strSubject, strBeamline, strProposal, strPrefix, strHost, strTime, ) else: strSubject = "EDNA %s : %s (%s)" % (_strSubject, EDUtilsPath.getEdnaSite(), strTime) self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.sendEmail: Subject = %s" % strSubject) self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.sendEmail: Message:") self.DEBUG(_strMessage) if self.strEDNAContactEmail == None: self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.sendEmail: No email address configured!") elif not EDUtilsPath.getEdnaSite().startswith("ESRF"): self.DEBUG( "EDPluginControlInterfaceToMXCuBEv1_4.sendEmail: Not executed at the ESRF! EDNA_SITE=%s" % EDUtilsPath.getEdnaSite() ) else: try: self.DEBUG("Sending message to %s." % self.strEDNAContactEmail) self.DEBUG("Message: %s" % _strMessage) strMessage = "EDNA_HOME = %s\n" % EDUtilsPath.getEdnaHome() strMessage += "EDNA_SITE = %s\n" % EDUtilsPath.getEdnaSite() strMessage += "PLUGIN_NAME = %s\n" % self.getPluginName() strMessage += "working_dir = %s\n\n" % self.getWorkingDirectory() strMessage += "Reference images:\n" xsDataInputMXCuBE = self.getDataInput() for xsDataSetMXCuBE in xsDataInputMXCuBE.getDataSet(): for xsDataFile in xsDataSetMXCuBE.getImageFile(): strMessage += "%s\n" % xsDataFile.getPath().getValue() strMessage += "\n" strMessage += _strMessage strEmailMsg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s" % ( self.strEDNAEmailSender, self.strEDNAContactEmail, strSubject, strMessage, ) server = smtplib.SMTP("localhost") server.sendmail(self.strEDNAEmailSender, self.strEDNAContactEmail, strEmailMsg) server.quit() except: self.ERROR("Error when sending email message!") self.writeErrorTrace() def executeSimpleHTML(self, _xsDataResultCharacterisation): xsDataInputSimpleHTMLPage = XSDataInputSimpleHTMLPage() xsDataInputSimpleHTMLPage.setCharacterisationResult(_xsDataResultCharacterisation) self.edPluginExecSimpleHTML.setDataInput(xsDataInputSimpleHTMLPage) self.edPluginExecSimpleHTML.connectSUCCESS(self.doSuccessSimpleHTML) self.edPluginExecSimpleHTML.connectFAILURE(self.doFailureSimpleHTML) self.executePluginSynchronous(self.edPluginExecSimpleHTML) def doSuccessSimpleHTML(self, _edPlugin=None): self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.doSuccessSimpleHTML...") self.retrieveSuccessMessages(_edPlugin, "EDPluginControlInterfaceToMXCuBEv1_4.doSuccessSimpleHTML") # Copy files from working directory if self.dataInput.htmlDir is None: self.xsDataResultMXCuBE.setHtmlPage(_edPlugin.dataOutput.pathToHTMLFile) else: htmlDir = self.dataInput.htmlDir.path.value if os.path.exists(htmlDir): # Potentially unsafe but very unlikely that this will cause problems htmlDir = tempfile.mktemp(prefix=os.path.basename(htmlDir), dir=os.path.dirname(htmlDir)) shutil.copytree(os.path.dirname(_edPlugin.dataOutput.pathToHTMLFile.path.value), htmlDir) htmlPage = os.path.join(htmlDir, os.path.basename(_edPlugin.dataOutput.pathToHTMLFile.path.value)) self.xsDataResultMXCuBE.setHtmlPage(XSDataFile(XSDataString(htmlPage))) def doFailureSimpleHTML(self, _edPlugin=None): self.DEBUG("EDPluginControlInterfaceToMXCuBEv1_4.doFailureSimpleHTML...") def makeNumberOfImagesMultipleOf100(self, _xsDataResultCharacterisation): xsDataResultCharacterisation = _xsDataResultCharacterisation.copy() strategyResult = xsDataResultCharacterisation.strategyResult if strategyResult is not None: for collectionPlan in strategyResult.collectionPlan: for subWedge in collectionPlan.collectionStrategy.subWedge: rotationAxisStart = subWedge.experimentalCondition.goniostat.rotationAxisStart.value rotationAxisEnd = subWedge.experimentalCondition.goniostat.rotationAxisEnd.value oscillationWidth = subWedge.experimentalCondition.goniostat.oscillationWidth.value noImages = int((rotationAxisEnd - rotationAxisStart) / oscillationWidth) self.screen( "Strategy: number of images for subWedge #{0}: {1}".format( subWedge.subWedgeNumber.value, noImages ) ) return xsDataResultCharacterisation