def run(self, inData):
     outData = {}
     # First get the list of subWedges
     if "subWedge" in inData:
         list_sub_wedge = inData["subWedge"]
         directory_prefix = ""
     else:
         first_image = inData["imagePath"][0]
         last_image = inData["imagePath"][-1]
         prefix = UtilsImage.getPrefix(first_image)
         first_image_number = UtilsImage.getImageNumber((first_image))
         last_image_number = UtilsImage.getImageNumber((last_image))
         directory_prefix = "{0}_{1}_{2}".format(
             prefix, first_image_number, last_image_number
         )
         list_sub_wedge = self.getListSubWedge(inData)
     indata_xds_integration = {
         "subWedge": list_sub_wedge
     }
     xds_integration = XDSIndexAndIntegration(
         inData=indata_xds_integration,
         workingDirectorySuffix=directory_prefix,
     )
     xds_integration.execute()
     outData = xds_integration.outData
     return outData
 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
Exemple #3
0
 def getH5FilePath(cls, filePath, batchSize=1, isFastMesh=False):
     imageNumber = UtilsImage.getImageNumber(filePath)
     prefix = UtilsImage.getPrefix(filePath)
     if isFastMesh:
         h5ImageNumber = int((imageNumber - 1) / 100) + 1
         h5FileNumber = 1
     else:
         h5ImageNumber = 1
         h5FileNumber = int((imageNumber - 1) / batchSize) * batchSize + 1
     h5MasterFileName = "{prefix}_{h5FileNumber}_master.h5".format(
         prefix=prefix, h5FileNumber=h5FileNumber)
     h5MasterFilePath = filePath.parent / h5MasterFileName
     h5DataFileName = \
         "{prefix}_{h5FileNumber}_data_{h5ImageNumber:06d}.h5".format(
             prefix=prefix, h5FileNumber=h5FileNumber, h5ImageNumber=h5ImageNumber)
     h5DataFilePath = filePath.parent / h5DataFileName
     return h5MasterFilePath, h5DataFilePath, h5FileNumber
Exemple #4
0
def findDataCollectionFromFileLocationAndFileName(imagePath, client=None):
    logger = UtilsLogging.getLogger()
    dataCollectionWS3VO = None
    noTrials = 10
    fileLocation = os.path.dirname(imagePath)
    fileName = os.path.basename(imagePath)
    if fileName.endswith(".h5"):
        prefix = UtilsImage.getPrefix(fileName)
        imageNumber = UtilsImage.getImageNumber(fileName)
        fileName = "{0}_{1:04d}.h5".format(prefix, imageNumber)
    try:
        if client is None:
            client = getCollectionWebService()
        if client is None:
            logger.error(
                "No web service client available, cannot contact findDataCollectionFromFileLocationAndFileName web service."
            )
        elif fileLocation is None:
            logger.error(
                "No fileLocation given, cannot contact findDataCollectionFromFileLocationAndFileName web service."
            )
        elif fileName is None:
            logger.error(
                "No fileName given, cannot contact findDataCollectionFromFileLocationAndFileName web service."
            )
        else:
            dataCollectionWS3VO = client.service.findDataCollectionFromFileLocationAndFileName(
                fileLocation, fileName)
    except Exception as e:
        logger.error(
            "ISPyB error for findDataCollectionFromFileLocationAndFileName: {0}, {1} trials left"
            .format(e, noTrials))
        raise e
    if dataCollectionWS3VO is None:
        time.sleep(1)
        if noTrials == 0:
            raise RuntimeError(
                "ISPyB error for findDataCollectionFromFileLocationAndFileName - no data collections found for path {0}"
                .format(imagePath))
        else:
            logger.warning(
                "Cannot find {0} in ISPyB - retrying, {1} trials left".format(
                    imagePath, noTrials))
    return dataCollectionWS3VO
 def createCBFHeaderData(cls, imagePath):
     # Waiting for file
     timedOut, finalSize = UtilsPath.waitForFile(imagePath,
                                                 expectedSize=100000,
                                                 timeOut=DEFAULT_TIME_OUT)
     if timedOut:
         errorMessage = "Timeout when waiting for image %s" % imagePath
         logger.error(errorMessage)
         raise BaseException(errorMessage)
     dictHeader = cls.readCBFHeader(imagePath)
     detector = dictHeader['Detector:']
     if 'PILATUS 3M' in detector or 'PILATUS3 2M' in detector or \
             'PILATUS 2M' in detector or 'PILATUS2 3M' in detector:
         detectorName = 'PILATUS2 3M'
         detectorType = 'pilatus2m'
         numberPixelX = 1475
         numberPixelY = 1679
     elif 'PILATUS 6M' in detector or 'PILATUS3 6M' in detector:
         detectorName = 'PILATUS2 6M'
         detectorType = 'pilatus6m'
         numberPixelX = 2463
         numberPixelY = 2527
     else:
         raise RuntimeError(
             '{0} cannot read image header from images with dector type {1}'
             .format(cls.__class__.__name__, detector))
     experimentalCondition = {}
     detector = {'numberPixelX': numberPixelX, 'numberPixelY': numberPixelY}
     # Pixel size
     listPixelSizeXY = dictHeader['Pixel_size'].split(' ')
     detector['pixelSizeX'] = float(listPixelSizeXY[0]) * 1000
     detector['pixelSizeY'] = float(listPixelSizeXY[3]) * 1000
     # Beam position
     listBeamPosition = dictHeader['Beam_xy'].replace('(', ' ').replace(
         ')', ' ').replace(',', ' ').split()
     detector['beamPositionX'] = float(listBeamPosition[0]) * \
                                 detector['pixelSizeX']
     detector['beamPositionY'] = float(listBeamPosition[1]) * \
                                 detector['pixelSizeY']
     distance = float(dictHeader['Detector_distance'].split(' ')[0]) * 1000
     detector['distance'] = distance
     detector['serialNumber'] = dictHeader['Detector:']
     detector['name'] = detectorName
     detector['type'] = detectorType
     experimentalCondition['detector'] = detector
     # Beam object
     beam = {
         'wavelength': float(dictHeader['Wavelength'].split(' ')[0]),
         'exposureTime': float(dictHeader['Exposure_time'].split(' ')[0])
     }
     experimentalCondition['beam'] = beam
     # Goniostat object
     goniostat = {}
     rotationAxisStart = float(dictHeader['Start_angle'].split(' ')[0])
     oscillationWidth = float(dictHeader['Angle_increment'].split(' ')[0])
     goniostat['rotationAxisStart'] = rotationAxisStart
     goniostat['rotationAxisEnd'] = rotationAxisStart + oscillationWidth
     goniostat['oscillationWidth'] = oscillationWidth
     experimentalCondition['goniostat'] = goniostat
     # Create the image object
     image = {'path': imagePath}
     if 'DateTime' in dictHeader:
         image['date'] = dictHeader['DateTime']
     imageNumber = UtilsImage.getImageNumber(imagePath)
     image['number'] = imageNumber
     subWedge = {
         'experimentalCondition': experimentalCondition,
         'image': [image]
     }
     return subWedge
Exemple #6
0
 def createThumbnail(
     image,
     format="jpg",
     height=512,
     width=512,
     outputPath=None,
     minLevel=0,
     maxLevel=99.95,
     dilatation=4,
     workingDirectory=None,
     outputFileName=None,
     doResolutionRings=False,
     pixelSizeX=None,
     pixelSizeY=None,
     beamPositionX=None,
     beamPositionY=None,
     distance=None,
     wavelength=None,
 ):
     imageFileName = os.path.basename(image)
     imagePath = image
     imageNameWithoutSuffix, imageSuffix = os.path.splitext(imageFileName)
     if imageSuffix == ".h5":
         imageNumber = UtilsImage.getImageNumber(image)
         h5MasterFilePath, h5DataFilePath, h5FileNumber = UtilsImage.getH5FilePath(
             image, isFastMesh=True)
         noTrials = 5
         fabioImage = None
         while noTrials > 0:
             try:
                 fabioImage = fabio.openimage.openimage(h5MasterFilePath)
                 noTrials = 0
             except Exception as e:
                 logger.debug("Error when trying to open {0}: {1}".format(
                     h5MasterFilePath, e))
                 logger.debug(
                     "Sleeping 5s and trying again, {0} trials left".format(
                         noTrials))
                 noTrials -= 1
                 time.sleep(5)
         if fabioImage is None:
             raise RuntimeError(
                 "Cannot open file {0} with fabio".format(h5MasterFilePath))
         logger.debug("No frames: {0}".format(fabioImage.nframes))
         if imageNumber < fabioImage.nframes:
             numpyImage = fabioImage.getframe(imageNumber).data
         else:
             numpyImage = fabioImage.data
         if numpyImage.dtype == numpy.dtype("uint32"):
             numpyImage = numpy.where(numpyImage > 65536 * 65536 - 2, 0,
                                      numpyImage)
         else:
             numpyImage = numpy.where(numpyImage > 256 * 256 - 2, 0,
                                      numpyImage)
     else:
         fabioImage = fabio.openimage.openimage(image)
         numpyImage = fabioImage.data
     # Default format
     suffix = "jpg"
     pilFormat = "JPEG"
     if format is not None:
         if format.lower() == "png":
             suffix = "png"
             pilFormat = "PNG"
     # The following code has been adapted from EDPluginExecThumbnail written by J.Kieffer
     dtype = numpyImage.dtype
     sortedArray = numpyImage.flatten()
     sortedArray.sort()
     numpyImage = numpy.maximum(numpyImage,
                                int(minLevel) * numpy.ones_like(numpyImage))
     maxLevel = sortedArray[int(
         round(float(maxLevel) * sortedArray.size / 100.0))]
     if maxLevel < 25:
         maxLevel = 25
     numpyImage = numpy.minimum(numpyImage,
                                maxLevel * numpy.ones_like(numpyImage))
     numpyImage = scipy.ndimage.morphology.grey_dilation(
         numpyImage, (dilatation, dilatation))
     mumpyImageFloat = (numpyImage.astype(numpy.float32)) / float(maxLevel)
     numpyImageInt = (mumpyImageFloat * 255.0).astype(numpy.uint8)
     # Check if we should do resolution rings
     listResolution = []
     if doResolutionRings:
         delta = (height + width) / 2000
         if delta < 1.0:
             delta = 1.0
         centreX = beamPositionX / pixelSizeX
         centreY = beamPositionY / pixelSizeY
         sizeY, sizeX = numpyImageInt.shape
         averageSize = (sizeX + sizeY) / 2.0
         yy, xx = numpy.mgrid[:sizeY, :sizeX]
         circle = (xx - centreX)**2 + (yy - centreY)**2
         for resolution in [1.0, 1.1, 1.2, 1.5, 2.0, 3.0, 4.0]:
             import math
             theta = math.asin(wavelength / (2 * resolution))
             radius = math.tan(2 * theta) * distance / pixelSizeX
             listResolution.append((resolution, radius / averageSize))
             numpyImageInt = numpy.where(
                 numpy.logical_and(circle < (radius + delta)**2, circle >
                                   (radius - delta)**2), 254, numpyImageInt)
     pilOutputImage = ImageOps.invert(Image.fromarray(numpyImageInt, 'L'))
     if height is not None and width is not None:
         pilOutputImage = pilOutputImage.resize((width, height),
                                                Image.ANTIALIAS)
     width, height = pilOutputImage.size
     for resolution, distance in listResolution:
         centreX = width / 2
         centreY = height / 2
         textfont = ImageFont.truetype(
             "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
             int(height / 30),
             encoding="unic")
         resolutionText = "{0} Å".format(resolution)
         imageEditable = ImageDraw.Draw(pilOutputImage)
         newDistance = distance * (height + width) / 2.0 / math.sqrt(2)
         imageEditable.text((centreX + newDistance - width / 20,
                             centreY + newDistance - height / 20),
                            resolutionText,
                            0,
                            font=textfont)
     if width * height > ImageFile.MAXBLOCK:
         ImageFile.MAXBLOCK = width * height
     if outputPath is None:
         if outputFileName is None:
             outputPath = os.path.join(
                 workingDirectory,
                 os.path.splitext(imageFileName)[0] + "." + suffix)
         else:
             outputPath = os.path.join(workingDirectory, outputFileName)
     pilOutputImage.save(outputPath, pilFormat, quality=85, optimize=True)
     logger.info("Output thumbnail path: %s" % outputPath)
     return outputPath
Exemple #7
0
 def test_getImageNumber(self):
     imageNumber = UtilsImage.getImageNumber(self.imageFileName)
     self.assertEqual(imageNumber, 1)
Exemple #8
0
    def generateImageLinks(in_data, working_directory=None):
        first_sub_wedge = in_data["subWedge"][0]
        first_image_path = first_sub_wedge["image"][0]["path"]
        prefix = UtilsImage.getPrefix(first_image_path)
        suffix = UtilsImage.getSuffix(first_image_path)
        if suffix == "h5":
            lowest_xds_image_number = 1
            highest_xds_image_number = 1
            h5MasterFilePath, h5DataFilePath, h5FileNumber = UtilsImage.getH5FilePath(
                first_image_path, hasOverlap=True, isFastMesh=False)
            h5MasterFile = os.path.basename((str(h5MasterFilePath)))
            h5DataFile = os.path.basename((str(h5DataFilePath)))
            list_image_link = [
                [str(h5MasterFilePath), h5MasterFile],
                [str(h5DataFilePath), h5DataFile],
            ]
            if working_directory is not None:
                os.symlink(str(h5MasterFilePath), h5MasterFile)
                os.symlink(str(h5DataFilePath), h5DataFile)
            template = h5MasterFile.replace("master", "??????")
            lowest_xds_image_number = None
            highest_xds_image_number = None
            for subwedge in in_data["subWedge"]:
                image_list = subwedge["image"]
                for image_dict in image_list:
                    image_path = image_dict["path"]
                    image_number = UtilsImage.getImageNumber(image_path)
                    if lowest_xds_image_number is None or lowest_xds_image_number > image_number:
                        lowest_xds_image_number = image_number
                    if highest_xds_image_number is None or highest_xds_image_number < image_number:
                        highest_xds_image_number = image_number
        else:
            template = "%s_xdslink_?????.%s" % (prefix, suffix)
            xds_lowest_image_number_global = 1
            # First we have to find the smallest goniostat rotation axis start:
            oscillation_start_min = 0

            # Loop through the list of sub wedges
            list_of_list = []
            lowest_xds_image_number = None
            highest_xds_image_number = None
            list_spot_range = []
            for sub_wedge in in_data["subWedge"]:
                list_image_link = []
                image_list = sub_wedge["image"]
                goniostat = sub_wedge["experimentalCondition"]["goniostat"]
                oscillation_start = goniostat["rotationAxisStart"]
                oscillation_range = goniostat["oscillationWidth"]

                # First find the lowest and highest image numbers
                lowest_image_number = None
                for image in image_list:
                    image_number = image["number"]
                    if lowest_image_number is None or image_number < lowest_image_number:
                        lowest_image_number = image_number

                # Loop through the list of images
                spot_range_min = None
                spot_range_max = None
                for image in image_list:
                    image_number = image["number"]
                    image_oscillation_start = (
                        oscillation_start +
                        (image_number - lowest_image_number) *
                        oscillation_range)
                    # if xdsLowestImageNumberGlobal is None:
                    #     xdsLowestImageNumberGlobal = 1 + int((imageOscillationStart - oscillationStartMin) / oscillationRange)
                    xds_image_number = xds_lowest_image_number_global + int(
                        (image_oscillation_start - oscillation_start_min) /
                        oscillation_range + 0.5)
                    print(
                        xds_image_number,
                        image_oscillation_start,
                        oscillation_start_min,
                        oscillation_range,
                    )
                    source_path = image["path"]
                    target = "%s_xdslink_%05d.%s" % (prefix, xds_image_number,
                                                     suffix)
                    print([source_path, target])
                    list_image_link.append([source_path, target])
                    if working_directory is not None and not os.path.exists(
                            target):
                        os.symlink(source_path, target)
                    if (lowest_xds_image_number is None
                            or lowest_xds_image_number > xds_image_number):
                        lowest_xds_image_number = xds_image_number
                    if (highest_xds_image_number is None
                            or highest_xds_image_number < xds_image_number):
                        highest_xds_image_number = xds_image_number
                    if spot_range_min is None or spot_range_min > xds_image_number:
                        spot_range_min = xds_image_number
                    if spot_range_max is None or spot_range_max < xds_image_number:
                        spot_range_max = xds_image_number
                list_spot_range.append([spot_range_min, spot_range_max])
                list_of_list.append(list_image_link)
        previous_exclude_data_range_max = 1
        list_exclude_data_range = []
        for spot_range_min, spot_range_max in list_spot_range:
            if spot_range_min > previous_exclude_data_range_max + 1:
                list_exclude_data_range.append(
                    [previous_exclude_data_range_max, spot_range_min - 1])
            previous_exclude_data_range_max = spot_range_max + 1
        dictImageLinks = {
            "imageLink": list_of_list,
            "spotRange": list_spot_range,
            "dataRange": [lowest_xds_image_number, highest_xds_image_number],
            "excludeDataRange": list_exclude_data_range,
            "template": template,
        }
        return dictImageLinks
Exemple #9
0
 def createHdf5HeaderData(cls,
                          imagePath,
                          skipNumberOfImages=False,
                          hasOverlap=False,
                          isFastMesh=True):
     h5MasterFilePath, h5DataFilePath, h5FileNumber = UtilsImage.getH5FilePath(
         pathlib.Path(imagePath),
         isFastMesh=isFastMesh,
         hasOverlap=hasOverlap)
     # Waiting for file
     timedOut, finalSize = UtilsPath.waitForFile(h5MasterFilePath,
                                                 expectedSize=2000000,
                                                 timeOut=DEFAULT_TIME_OUT)
     if timedOut:
         errorMessage = "Timeout when waiting for image %s" % imagePath
         logger.error(errorMessage)
         raise BaseException(errorMessage)
     logger.info("Final size for {0}: {1}".format(h5MasterFilePath,
                                                  finalSize))
     noTrialsLeft = 5
     dictHeader = None
     while noTrialsLeft > 0:
         try:
             dictHeader = cls.readHdf5Header(h5MasterFilePath)
             noTrialsLeft = 0
         except Exception as e:
             logger.warning(
                 "Cannot read header from {0}, no trials left: {1}".format(
                     h5MasterFilePath, noTrialsLeft))
             time.sleep(5)
             noTrialsLeft -= 1
     if dictHeader is None:
         raise RuntimeError(
             "Cannot read header from {0}!".format(h5MasterFilePath))
     description = dictHeader["description"]
     if "Eiger 4M" in description:
         detectorName = "EIGER 4M"
         detectorType = "eiger4m"
         numberPixelX = 2070
         numberPixelY = 2167
     elif "eiger" in description.lower() and "16M" in description:
         detectorName = "EIGER 16M"
         detectorType = "eiger16m"
         numberPixelX = 4148
         numberPixelY = 4362
     else:
         raise RuntimeError(
             "{0} cannot read image header from images with detector type {1}"
             .format(cls.__class__.__name__, description))
     # Image number
     image_number = UtilsImage.getImageNumber(imagePath)
     # Find out size of data set
     prefix = str(h5MasterFilePath).split("master")[0]
     listDataImage = []
     noImages = 0
     if not skipNumberOfImages:
         for data in dictHeader["data"]:
             dataFilePath = prefix + data + ".h5"
             timedOut, finalSize = UtilsPath.waitForFile(
                 dataFilePath,
                 expectedSize=100000,
                 timeOut=DEFAULT_TIME_OUT)
             if timedOut:
                 raise RuntimeError(
                     "Timeout waiting for file {0}".format(dataFilePath))
             # listDataImage.append({
             #     'path': dataFilePath
             # })
             f = h5py.File(dataFilePath, "r")
             dataShape = f["entry"]["data"]["data"].shape
             noImages += dataShape[0]
             f.close()
     experimentalCondition = {}
     # Pixel size and beam position
     detector = {
         "numberPixelX":
         int(numberPixelX),
         "numberPixelY":
         int(numberPixelY),
         "pixelSizeX":
         round(dictHeader["x_pixel_size"] * 1000, 3),
         "pixelSizeY":
         round(dictHeader["y_pixel_size"] * 1000, 3),
         "beamPositionX":
         round(
             float(dictHeader["beam_center_x"] *
                   dictHeader["x_pixel_size"] * 1000),
             3,
         ),
         "beamPositionY":
         round(
             float(dictHeader["beam_center_y"] *
                   dictHeader["y_pixel_size"] * 1000),
             3,
         ),
         "distance":
         round(float(dictHeader["detector_distance"]) * 1000, 3),
         "serialNumber":
         dictHeader["detector_number"],
         "name":
         detectorName,
         "type":
         detectorType,
     }
     experimentalCondition["detector"] = detector
     # Beam object
     beam = {
         "wavelength": round(float(dictHeader["wavelength"]), 6),
         "exposureTime": round(float(dictHeader["count_time"]), 6),
     }
     experimentalCondition["beam"] = beam
     # Goniostat object
     goniostat = {}
     rotationAxisStart = round(float(dictHeader["omega_start"]), 4)
     oscillationWidth = round(float(dictHeader["omega_range_average"]), 4)
     # Offset for the image number
     rotationAxisStart += (image_number - 1) * oscillationWidth
     goniostat["rotationAxisStart"] = rotationAxisStart
     goniostat["rotationAxisEnd"] = rotationAxisStart + oscillationWidth
     goniostat["oscillationWidth"] = oscillationWidth
     experimentalCondition["goniostat"] = goniostat
     # Create the image object
     image_dict = {
         "path": imagePath,
         "date": dictHeader["data_collection_date"],
         "number": 1,
     }
     # imageNumber = UtilsImage.getImageNumber(imagePath)
     # image['number'] = imageNumber
     subWedge = {
         "experimentalCondition": experimentalCondition,
         "image": [image_dict],
     }
     return subWedge
Exemple #10
0
 def createCBFHeaderData(cls, imagePath):
     # Waiting for file
     timedOut, finalSize = UtilsPath.waitForFile(imagePath,
                                                 expectedSize=100000,
                                                 timeOut=DEFAULT_TIME_OUT)
     if timedOut:
         errorMessage = "Timeout when waiting for image %s" % imagePath
         logger.error(errorMessage)
         raise BaseException(errorMessage)
     dictHeader = cls.readCBFHeader(imagePath)
     detector = dictHeader["Detector:"]
     if ("PILATUS 3M" in detector or "PILATUS3 2M" in detector
             or "PILATUS 2M" in detector or "PILATUS2 3M" in detector):
         detectorName = "PILATUS2 3M"
         detectorType = "pilatus2m"
         numberPixelX = 1475
         numberPixelY = 1679
     elif "PILATUS 6M" in detector or "PILATUS3 6M" in detector:
         detectorName = "PILATUS2 6M"
         detectorType = "pilatus6m"
         numberPixelX = 2463
         numberPixelY = 2527
     elif "eiger" in detector.lower() and "4m" in detector.lower():
         detectorName = "EIGER 4M"
         detectorType = "eiger4m"
         numberPixelX = 2070
         numberPixelY = 2167
     elif "eiger2" in detector.lower() and "16m" in detector.lower():
         detectorName = "EIGER2 16M"
         detectorType = "eiger16m"
         numberPixelX = 4148
         numberPixelY = 4362
     else:
         raise RuntimeError(
             "{0} cannot read image header from images with dector type {1}"
             .format(cls.__class__.__name__, detector))
     experimentalCondition = {}
     detector = {"numberPixelX": numberPixelX, "numberPixelY": numberPixelY}
     # Pixel size
     listPixelSizeXY = dictHeader["Pixel_size"].split(" ")
     detector["pixelSizeX"] = float(listPixelSizeXY[0]) * 1000
     detector["pixelSizeY"] = float(listPixelSizeXY[3]) * 1000
     # Beam position
     listBeamPosition = (dictHeader["Beam_xy"].replace("(", " ").replace(
         ")", " ").replace(",", " ").split())
     detector["beamPositionX"] = float(
         listBeamPosition[0]) * detector["pixelSizeX"]
     detector["beamPositionY"] = float(
         listBeamPosition[1]) * detector["pixelSizeY"]
     distance = float(dictHeader["Detector_distance"].split(" ")[0]) * 1000
     detector["distance"] = distance
     detector["serialNumber"] = dictHeader["Detector:"]
     detector["name"] = detectorName
     detector["type"] = detectorType
     experimentalCondition["detector"] = detector
     # Beam object
     beam = {
         "wavelength": float(dictHeader["Wavelength"].split(" ")[0]),
         "exposureTime": float(dictHeader["Exposure_time"].split(" ")[0]),
     }
     experimentalCondition["beam"] = beam
     # Goniostat object
     goniostat = {}
     rotationAxisStart = float(dictHeader["Start_angle"].split(" ")[0])
     oscillationWidth = float(dictHeader["Angle_increment"].split(" ")[0])
     goniostat["rotationAxisStart"] = rotationAxisStart
     goniostat["rotationAxisEnd"] = rotationAxisStart + oscillationWidth
     goniostat["oscillationWidth"] = oscillationWidth
     experimentalCondition["goniostat"] = goniostat
     # Create the image object
     image = {"path": imagePath}
     if "DateTime" in dictHeader:
         image["date"] = dictHeader["DateTime"]
     imageNumber = UtilsImage.getImageNumber(imagePath)
     image["number"] = imageNumber
     subWedge = {
         "experimentalCondition": experimentalCondition,
         "image": [image]
     }
     return subWedge
Exemple #11
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
Exemple #12
0
    def run(self, inData):
        listImagePath = inData["imagePath"]
        prefix = UtilsImage.getPrefix(listImagePath[0])
        listSubWedge = self.getListSubWedge(inData)
        diffractionPlan = inData.get("diffractionPlan", {})
        sample = inData.get("sample", {})
        # Check if flux is present
        flux = None
        absorbedDoseRate = None
        experimentalCondition = inData.get("experimentalCondition", None)
        if experimentalCondition is not None:
            beam = experimentalCondition.get("beam", None)
            if beam is not None:
                flux = beam.get("flux", None)
                # if not "size" in beam:
                #     beam["size"] = listSubWedge[0]["experimentalCondition"]["beam"]["size"]
                beam["exposureTime"] = listSubWedge[0][
                    "experimentalCondition"]["beam"]["exposureTime"]
                beam["wavelength"] = listSubWedge[0]["experimentalCondition"][
                    "beam"]["wavelength"]
        # Convert images to CBF
        firstImage = listSubWedge[0]["image"][0]["path"]
        import os
        import pprint

        listH5ToCBF = []
        suffix = os.path.splitext(firstImage)[1]
        if suffix == ".h5":
            for subWedge in listSubWedge:
                imageList = subWedge["image"]
                for image in imageList:
                    imagePath = image["path"]
                    hdf5ImageNumber = UtilsImage.getImageNumber(imagePath)
                    inDataH5ToCBF = {
                        "hdf5File": imagePath,
                        "hdf5ImageNumber": hdf5ImageNumber,
                        "imageNumber": 1,
                        "forcedOutputDirectory":
                        str(self.getWorkingDirectory()),
                        "forcedOutputImageNumber": hdf5ImageNumber,
                    }
                    h5ToCBF = H5ToCBFTask(inData=inDataH5ToCBF)
                    h5ToCBF.start()
                    listH5ToCBF.append((image, h5ToCBF))
        # Join CBF creation
        for image, h5ToCBF in listH5ToCBF:
            h5ToCBF.join()
            image["path"] = h5ToCBF.outData["outputCBFFile"]
        pprint.pprint(listSubWedge)
        # Start indexing
        outDataIndexing, outDataGB, listSubWedge = self.indexing(
            prefix, listSubWedge, self.getWorkingDirectory())
        if outDataIndexing is not None and outDataGB is not None:
            listXdsAsciiHkl, correctLp, bkgpixCbf = self.integration(
                prefix, listSubWedge, outDataIndexing, outDataGB)
            if listXdsAsciiHkl is not None:
                # Check if Raddose should be run
                estimateRadiationDamage = self.checkEstimateRadiationDamage(
                    inData, flux)
                if estimateRadiationDamage:
                    # Check if forced space group
                    forcedSpaceGroup = None
                    numOperators = None
                    cell = None
                    if ("diffractionPlan" in inData and "forcedSpaceGroup"
                            in inData["diffractionPlan"]):
                        forcedSpaceGroup = inData["diffractionPlan"][
                            "forcedSpaceGroup"]
                        if forcedSpaceGroup is not None:
                            if forcedSpaceGroup != "":
                                forcedSpaceGroup = forcedSpaceGroup.replace(
                                    " ", "")
                                numOperators = UtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupName(
                                    forcedSpaceGroup)
                            else:
                                forcedSpaceGroup = None
                    if forcedSpaceGroup is None:
                        # Get indexing space group IT number
                        if "resultIndexing" in outDataIndexing:
                            resultIndexing = outDataIndexing["resultIndexing"]
                            cell = resultIndexing["cell"]
                            if "spaceGroupNumber" in resultIndexing:
                                spaceGroupNumber = resultIndexing[
                                    "spaceGroupNumber"]
                                numOperators = UtilsSymmetry.getNumberOfSymmetryOperatorsFromSpaceGroupITNumber(
                                    spaceGroupNumber)
                    if numOperators is None:
                        raise RuntimeError(
                            "Error when trying to determine number of symmetry operators!"
                        )
                    chemicalComposition = self.getDefaultChemicalComposition(
                        cell, numOperators)
                    numberOfImages = self.getNumberOfImages(listSubWedge)
                    sample = inData["sample"]
                    inDataRaddose = {
                        "experimentalCondition": experimentalCondition,
                        "chemicalComposition": chemicalComposition,
                        "sample": sample,
                        "cell": cell,
                        "numberOfImages": numberOfImages,
                        "numOperators": numOperators,
                    }
                    # import pprint
                    # pprint.pprint(inDataRaddose)
                    raddose = Raddose(inData=inDataRaddose,
                                      workingDirectorySuffix=prefix)
                    raddose.execute()
                    if raddose.isSuccess():
                        absorbedDoseRate = raddose.outData["absorbedDoseRate"]
                inDataBest = {
                    "diffractionPlan": diffractionPlan,
                    "sample": sample,
                    "subWedge": listSubWedge,
                    "xdsAsciiHkl": listXdsAsciiHkl,
                    "bkgpixCbf": bkgpixCbf,
                    "correctLp": correctLp,
                    "crystalAbsorbedDoseRate": absorbedDoseRate,
                }
                bestTask = Best(inData=inDataBest,
                                workingDirectorySuffix=prefix)
                bestTask.execute()
Exemple #13
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