def createBatchList(self, inData):
     listOfBatches = []
     listOfImagesInBatch = []
     if len(self.listImage) == 0:
         self.directory = pathlib.Path(inData["directory"])
         self.template = inData["template"]
         startNo = inData["startNo"]
         endNo = inData["endNo"]
         for index in range(startNo, endNo + 1):
             listOfImagesInBatch.append(index)
             if len(listOfImagesInBatch) == self.batchSize or index == 9999:
                 listOfBatches.append(listOfImagesInBatch)
                 listOfImagesInBatch = []
     else:
         firstImage = pathlib.Path(self.listImage[0])
         self.directory = firstImage.parent
         self.template = UtilsImage.getTemplate(firstImage)
         for image in self.listImage:
             imageNo = UtilsImage.getImageNumber(image)
             listOfImagesInBatch.append(imageNo)
             if len(listOfImagesInBatch) == self.batchSize:
                 listOfBatches.append(listOfImagesInBatch)
                 listOfImagesInBatch = []
     if len(listOfImagesInBatch) > 0:
         listOfBatches.append(listOfImagesInBatch)
     return listOfBatches
Beispiel #2
0
 def test_getTemplateQuestionMark(self):
     template = UtilsImage.getTemplate(self.imageFileName, symbol="?")
     templateReference = "ref-testscale_1_????.img"
     self.assertEqual(templateReference, template)
Beispiel #3
0
 def test_getTemplateHash2(self):
     template = UtilsImage.getTemplate(self.imageFileName2)
     templateReference = "ref-testscale_1_#####.img"
     self.assertEqual(templateReference, template)
Beispiel #4
0
 def generateMOSFLMInData(cls, inData):
     if "imagePath" in inData:
         inDataReadImageHeader = {"imagePath": inData["imagePath"]}
         readImageHeader = ReadImageHeader(inData=inDataReadImageHeader)
         readImageHeader.execute()
         listSubWedges = readImageHeader.outData["subWedge"]
     elif "subWedge" in inData:
         listSubWedges = inData["subWedge"]
     else:
         # Here we assume that we have inData in MOSFLM format...
         return inData
     firstSubWedge = listSubWedges[0]
     experimentalCondition = firstSubWedge["experimentalCondition"]
     detector = experimentalCondition["detector"]
     beam = experimentalCondition["beam"]
     goniostat = experimentalCondition["goniostat"]
     detectorType = detector["type"]
     if detectorType.startswith("pilatus"):
         mosflmDetector = "PILATUS"
     elif detectorType.startswith("eiger"):
         mosflmDetector = "EIGER"
     else:
         raise RuntimeError("Unknown detecor type for MOSFLM: " +
                            detectorType)
     listImage = firstSubWedge["image"]
     firstImage = listImage[0]
     firstPath = firstImage["path"]
     mosflmInData = {
         # The MOSFLM beam position convention is opposite to the XDS / CBF/ Dozor convention
         "beam": {
             "x": detector["beamPositionY"],
             "y": detector["beamPositionX"]
         },
         "detector": {
             "numberPixelX": detector["numberPixelX"],
             "numberPixelY": detector["numberPixelY"],
             "pixelSizeX": detector["pixelSizeX"],
             "pixelSizeY": detector["pixelSizeY"],
             "type": mosflmDetector
         },
         "directory": os.path.dirname(firstPath),
         "distance": detector["distance"],
         "template": UtilsImage.getTemplate(firstPath),
         "wavelength": beam["wavelength"]
     }
     listMosflmImage = []
     for subWedge in listSubWedges:
         goniostat = subWedge["experimentalCondition"]["goniostat"]
         rotationAxisStart = goniostat['rotationAxisStart']
         oscillationWidth = goniostat['oscillationWidth']
         imageIndex = 0
         for image in subWedge["image"]:
             number = UtilsImage.getImageNumber(image["path"])
             rotationAxisStart = rotationAxisStart + oscillationWidth * imageIndex
             rotationAxisEnd = rotationAxisStart + oscillationWidth
             mosflmImage = {
                 "number": number,
                 "rotationAxisStart": rotationAxisStart,
                 "rotationAxisEnd": rotationAxisEnd
             }
             listMosflmImage.append(mosflmImage)
     mosflmInData["image"] = listMosflmImage
     return mosflmInData
Beispiel #5
0
    def run(self, inData):
        beamline = inData.get('beamline', None)
        doSubmit = inData.get('doSubmit', False)
        doDozorm = inData.get('doDozorm', False)
        batchSize = inData.get('batchSize', 1)
        doDistlSignalStrength = inData.get('doDistlSignalStrength', False)
        doIndexing = inData.get('doIndexing', False)
        if crystFelImportFailed:
            doCrystfel = False
        else:
            doCrystfel = inData.get('doCrystfel', True)
        isFastMesh = inData.get('fastMesh', False)
        # Loop through all the incoming reference images
        listImage = inData.get('image', [])
        if len(listImage) == 0:
            directory = pathlib.Path(inData['directory'])
            template = inData['template']
            startNo = inData['startNo']
            endNo = inData['endNo']
            listImage = []
            for index in range(startNo, endNo + 1):
                imageName = template.replace("####", "{0:04d}".format(index))
                imagePath = directory / imageName
                listImage.append(str(imagePath))
        else:
            firstImage = listImage[0]
            lastImage = listImage[-1]
            directory = pathlib.Path(firstImage).parent
            template = UtilsImage.getTemplate(firstImage)
            startNo = UtilsImage.getImageNumber(firstImage)
            endNo = UtilsImage.getImageNumber(lastImage)
        outData = dict()
        listImageQualityIndicators = []
        listcrystfel_output = []
        inDataWaitFile = {}
        listDistlTask = []
        listDozorTask = []
        listCrystFELTask = []
        listOfImagesInBatch = []
        listOfAllBatches = []
        listOfAllH5Files = []
        listControlDozorAllFile = []
        indexBatch = 0
        self.listH5FilePath = []
        detectorType = None
        # Configurations
        minImageSize = UtilsConfig.get(
            self, 'minImageSize', defaultValue=DEFAULT_MIN_IMAGE_SIZE)
        waitFileTimeOut = UtilsConfig.get(
            self, 'waitFileTimeOut', defaultValue=DEFAULT_WAIT_FILE_TIMEOUT)
        # Process data in batches
        for image in listImage:
            listOfImagesInBatch.append(pathlib.Path(image))
            if len(listOfImagesInBatch) == batchSize:
                listOfAllBatches.append(listOfImagesInBatch)
                listOfImagesInBatch = []
        if len(listOfImagesInBatch) > 0:
            listOfAllBatches.append(listOfImagesInBatch)
            listOfImagesInBatch = []
        if UtilsImage.getSuffix(pathlib.Path(listImage[0])) == 'h5':
            for image in listImage:
                listOfAllH5Files.append(pathlib.Path(image))
        #
        # Loop over batches:
        # - Wait for all files in batch
        # - Run Dozor and Crystfel (if required) in parallel
        #
        # Check if we should run CrystFEL:

        for listOfImagesInBatch in listOfAllBatches:
            listOfH5FilesInBatch = []
            for imagePath in listOfImagesInBatch:
                # First wait for images
                self.waitForImagePath(
                    imagePath=imagePath,
                    batchSize=batchSize,
                    isFastMesh=isFastMesh,
                    minImageSize=minImageSize,
                    waitFileTimeOut=waitFileTimeOut,
                    listofH5FilesInBatch=listOfH5FilesInBatch
                )
            if not self.isFailure():
                # Determine start and end image no
                pathToFirstImage = listOfImagesInBatch[0]
                pathToLastImage = listOfImagesInBatch[-1]
                batchStartNo = UtilsImage.getImageNumber(pathToFirstImage)
                batchEndNo = UtilsImage.getImageNumber(pathToLastImage)
                # Run Control Dozor
                inDataControlDozor = {
                    'template': template,
                    'directory': directory,
                    'startNo': batchStartNo,
                    'endNo': batchEndNo,
                    'batchSize': batchSize,
                    'doSubmit': doSubmit,
                    'doDozorm': doDozorm
                }
                if beamline is not None:
                    inDataControlDozor["beamline"] = beamline
                controlDozor = ControlDozor(
                    inDataControlDozor,
                    workingDirectorySuffix='{0:04d}_{1:04d}'.format(batchStartNo, batchEndNo))
                controlDozor.start()
                listDozorTask.append((controlDozor, inDataControlDozor,
                                      list(listOfImagesInBatch), listOfH5FilesInBatch))
                # Check if we should run distl.signalStrength
                if doDistlSignalStrength:
                    for image in listOfImagesInBatch:
                        inDataDistl = {
                            'referenceImage': str(image)
                        }
                        distlTask = DistlSignalStrengthTask(
                            inData=inDataDistl,
                            workingDirectorySuffix=UtilsImage.getImageNumber(image))
                        distlTask.start()
                        listDistlTask.append((image, distlTask))

        if not self.isFailure():
            # listIndexing = []
            listDistlResult = []
            # Synchronize all image quality indicator plugins and upload to ISPyB
            for (image, distlTask) in listDistlTask:
                imageQualityIndicators = {}
                if distlTask is not None:
                    distlTask.join()
                    if distlTask.isSuccess():
                        outDataDistl = distlTask.outData
                        if outDataDistl is not None:
                            imageQualityIndicators = outDataDistl['imageQualityIndicators']
                imageQualityIndicators['image'] = str(image)
                listDistlResult.append(imageQualityIndicators)
                # self.xsDataResultControlImageQualityIndicators.addImageQualityIndicators(xsDataImageQualityIndicators)
            for (controlDozor, inDataControlDozor, listBatch, listH5FilePath) in listDozorTask:
                controlDozor.join()
                # Check that we got at least one result
                if len(controlDozor.outData['imageQualityIndicators']) == 0:
                    # Run the dozor plugin again, this time synchronously
                    firstImage = listBatch[0].name
                    lastImage = listBatch[-1].name
                    logger.warning("No dozor results! Re-executing Dozor for" +
                                   " images {0} to {1}".format(firstImage, lastImage))
                    time.sleep(5)
                    controlDozor = ControlDozor(inDataControlDozor)
                    controlDozor.execute()
                listOutDataControlDozor = list(controlDozor.outData['imageQualityIndicators'])
                if detectorType is None:
                    detectorType = controlDozor.outData['detectorType']
                if doDistlSignalStrength:
                    for outDataControlDozor in listOutDataControlDozor:
                        for distlResult in listDistlResult:
                            if outDataControlDozor['image'] == distlResult['image']:
                                imageQualityIndicators = dict(outDataControlDozor)
                                imageQualityIndicators.update(distlResult)
                                listImageQualityIndicators.append(imageQualityIndicators)
                else:
                    listImageQualityIndicators += listOutDataControlDozor
                # Check if dozorm
                if doDozorm:
                    listControlDozorAllFile.append(controlDozor.outData['dozorAllFile'])

        if not self.isFailure() and doCrystfel:
            # Select only the strongest images to be run by CrystFEL
            listIndicatorsSorted = sorted(listImageQualityIndicators, key=lambda k: k['dozorScore'])[::-1]
            listForCrystFEL = [k['image'] for k in listIndicatorsSorted[0:min(200, len(listIndicatorsSorted))]]
            batchSize = 20
            if len(listForCrystFEL) % batchSize == 0:
                file_chunk = int(len(listForCrystFEL) / batchSize)
            else:
                file_chunk = int(len(listForCrystFEL) / batchSize) + 1
            for jj in range(file_chunk):
                start = batchSize * jj
                stop = batchSize * (jj + 1)
                try:
                    images = listForCrystFEL[start:stop]
                except IndexError:
                    stop = start + (len(listForCrystFEL) - stop)
                    images = listForCrystFEL[start:stop]

                inDataCrystFEL = {
                    'doCBFtoH5': False,
                    'cbfFileInfo': {
                        'directory': directory,
                        'template': template,
                        'batchSize': batchSize,
                        'listofImages': images
                    },
                    'doSubmit': doSubmit
                }
                crystfel = ExeCrystFEL(inData=inDataCrystFEL)
                crystfel.start()
                listCrystFELTask.append(crystfel)

            masterstream = str(self.getWorkingDirectory() / 'alltogether.stream')
            if not self.isFailure():
                for crystfel in listCrystFELTask:
                    crystfel.join()
                    if crystfel.isSuccess():
                        catcommand = "cat %s >> %s" % (crystfel.outData['streamfile'], masterstream)
                        AutoCrystFEL.run_as_command(catcommand)

            if not self.isFailure() and os.path.exists(masterstream):
                crystfel_outdata = AutoCrystFEL.report_stats(masterstream)
                crystfel_outdata['number of DozorHits'] = len(listForCrystFEL)
                AutoCrystFEL.write_cell_file(crystfel_outdata)
                listcrystfel_output.append(crystfel_outdata)
            else:
                logger.error("CrystFEL did not run properly")
        # Assemble all controlDozorAllFiles into one
        if doDozorm:
            imageQualityIndicatorsDozorAllFile = str(self.getWorkingDirectory() / "dozor_all")
            os.system('touch {0}'.format(imageQualityIndicatorsDozorAllFile))
            for controlDozorAllFile in listControlDozorAllFile:
                command = 'cat ' + controlDozorAllFile + ' >> ' + imageQualityIndicatorsDozorAllFile
                os.system(command)
            outData["dozorAllFile"] = imageQualityIndicatorsDozorAllFile

        outData['imageQualityIndicators'] = listImageQualityIndicators
        outData['crystfel_results'] = listcrystfel_output
        return outData