Example #1
0
def calc_image_and_save(img_sum: np.ndarray, img_num: int, dk_img: tp.Union[None, np.ndarray],
                        tiff_path: tp.Union[str, Path]) -> None:
    """Average the image, subtract the dark image and export the image in a tiff file."""
    avg_img = img_sum / img_num
    if dk_img is not None:
        avg_img = avg_img - dk_img
    tw = TiffWriter(tiff_path)
    tw.write(avg_img)
    return
Example #2
0
def run_pyfai_calib2(run: Header, data_key: str, output_dir: str = "xpdacq_calib",
                     file_prefix: str = r"{start[uid]}_", **kwargs) -> pyFAI.AzimuthalIntegrator:
    """Run the pyFAi calibration2 for a data entry in databroker."""
    output_dir = Path(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)
    args = ["pyFAI-calib2"]
    # add wavelength
    if "w" not in kwargs and "wavelength" not in kwargs and "bt_wavelength" in run.start:
        kwargs["wavelength"] = run.start["bt_wavelength"]
    # add poni file
    poni_path = output_dir.joinpath(
        file_prefix.format(start=run.start, stop=run.stop) + "{}.poni".format(data_key))
    kwargs["poni"] = str(poni_path)
    # add kwargs to args
    for k, v in kwargs.items():
        if len(k) == 1:
            args.append("-{}".format(k))
        else:
            args.append("--{}".format(k))
        args.append(str(v))
    # write out the file
    tiff_path = output_dir.joinpath(
        file_prefix.format(start=run.start, stop=run.stop) + "{}.tiff".format(data_key))
    avg_img: np.ndarray = _mean(run.data(data_key))
    tw = TiffWriter(str(tiff_path))
    tw.write(avg_img)
    args.append(str(tiff_path))
    # run the pyFAI-calib2
    cp = subprocess.run(args, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    if cp.returncode != 0:
        raise RuntimeError("Error in pyFAI-calib2:\n{}".format(cp.stderr.decode()))
    if not poni_path.is_file():
        raise FileNotFoundError(
            "No poni file {}. Did you change the file name when you save the poni file?".format(
                str(poni_path)))
    ai = pyFAI.load(str(poni_path))
    return ai
Example #3
0
def analysis_txt(widget,
                 imagelist,
                 roiname,
                 outlist,
                 expand_pixel,
                 roi_enlarge_pixel,
                 expand_f=0,
                 meth=None):

    num = int(len(outlist))
    """
    我们新建了一个QProgressDialog对象progress,设置它的标题、标签、增加取消的按钮。
    """
    progress = QProgressDialog(widget)
    progress.setWindowTitle("请稍等")
    progress.setLabelText("正在操作...")
    progress.setCancelButtonText("取消")
    """
    如果任务的预期持续时间小于minimumDuration,则对话框根本不会出现。这样可以防止弹出对话框,快速完成任务。对于预期超过minimumDuration的任务,对话框将在minimumDuration时间之后或任何进度设置后立即弹出。如果设置为0,则只要设置任何进度,将始终显示对话框。 默认值为4000毫秒,即4秒。
    """
    progress.setMinimumDuration(5)  #此属性保留对话框出现之前必须通过的时间。
    """
    此属性保留由模态小部件阻止的窗口。
    这个属性只对Windows有意义。 模态小部件防止其他窗口中的小部件获取输入。 该属性的值控制在窗口小部件可见时阻止哪些窗口。 窗口可见时更改此属性无效; 您必须首先hide()小部件,然后再次show()。
    默认情况下,此属性为Qt.NonModal。
    """
    progress.setWindowModality(Qt.WindowModal)
    """
    由上面我们知道:使用setMinimum() 和setMaximum() 或构造函数来设置操作中的“steps”数量,并在操作进行时调用setValue()。setRange(0,num)就是设置其最小和最大值,这里最小值0,最大值num,num是根据输入框中的数字确定的。
    """
    progress.setRange(0, num)
    """
    setValue()该属性持有当前的进度。要使进度对话框按预期的方式工作,您应该首先将此属性设置为QProgressDialog的最大最小值, 您可以在中间调用setValue()任意次数。
    通过wasCanceled()判断我们是否按下取消按钮,如果按下则提示失败。若for循环顺利结束,执行else后的语句,表明成功
    """

    roi2 = ImagejRoi.fromfile(roiname)
    outfilename = outlist[0] + "_shift.zip"
    if os.path.exists(outfilename):
        os.remove(outfilename)
    print('outfile:', outfilename)
    zip1 = zipfile.ZipFile(outfilename, 'w')
    zip1.close()
    #os.mkdir(os.path.join(pathway,name))
    for roi in roi2:
        roi.tofile(outfilename)
    img = Image.open(imagelist[0])
    img = np.asarray(img, dtype=np.float32)
    img_ori = img.copy()
    imgs = []

    path, filename = os.path.split(outlist[0])
    mergefile = os.path.join(path, "_merge.tif")
    tifroifile = os.path.join(path, "batch_sequence.txt")
    img_ori = draw_roi_onimage(roi2, img_ori)
    imgs.append(np.array(img_ori, dtype=np.uint16))

    count = 1
    for imagefile, outname, templatefile in zip(imagelist[1:], outlist[1:],
                                                imagelist[:-1]):
        progress.setValue(count)
        if progress.wasCanceled():
            QMessageBox.warning(widget, "提示", "操作失败")
            break
        count += 1

        roi2 = ImagejRoi.fromfile(outfilename)
        image_template = Image.open(templatefile)
        image_template = np.asarray(image_template, dtype=np.float32)

        print('processing file:', imagefile)
        img = Image.open(imagefile)
        print(img.format, img.size, img.mode)
        img = np.asarray(img, dtype=np.float32)
        img_ori = img.copy()
        img = match_histograms(img, image_template, multichannel=False)
        height, width = img.shape
        outofborder = 0

        # align first
        alignx, aligny = align.caculate_shift(image_template, img)

        alignx = stats.mode(alignx)[0][0]
        aligny = stats.mode(aligny)[0][0]
        print('alignx', -alignx, 'align_y', -aligny)
        img = np.roll(img, aligny, axis=0)
        img = np.roll(img, alignx, axis=1)

        # padding edge ,top,bottom,left,right
        # expand pixel
        # print(image_template.shape)
        image_template = cv2.copyMakeBorder(image_template,
                                            expand_pixel,
                                            expand_pixel,
                                            expand_pixel,
                                            expand_pixel,
                                            borderType=cv2.BORDER_REPLICATE)
        img = cv2.copyMakeBorder(img,
                                 expand_pixel,
                                 expand_pixel,
                                 expand_pixel,
                                 expand_pixel,
                                 borderType=cv2.BORDER_REPLICATE)
        # print(image_template.shape)
        for roi in roi2:
            a, b, c, d = roi.left, roi.bottom, roi.right, roi.top
            if a < 0 or b < 0 or c >= width or d >= height:
                print('err', a, b, c, d)

            roi.left = roi.left + expand_pixel
            roi.top = roi.top + expand_pixel
            roi.right = roi.right + expand_pixel
            roi.bottom = roi.bottom + expand_pixel

        roi_corners, roi_imgs, roi_offsets = _get_template_img_from_roi(
            image_template,
            roi2,
            expand_pixel=roi_enlarge_pixel,
            expand_f=expand_f)

        # match template
        pre_image = image_template
        roi_corners, roi_imgs, roi_offsets = _get_roiimg_from_match(
            img, pre_image, roi_corners, roi_imgs, roi_offsets, roi2,
            expand_pixel, expand_f, meth)
        pre_image = Image.open(imagefile)
        pre_image = np.asarray(pre_image)

        # write new roi
        outfilename = outname + "_shift.zip"
        if os.path.exists(outfilename):
            os.remove(outfilename)
        print('outfile:', outfilename)
        zip1 = zipfile.ZipFile(outfilename, 'w')
        zip1.close()
        #os.mkdir(os.path.join(pathway,name))
        for roi in roi2:
            shiftx, shifty = roi_offsets[roi.name][1]  # 0 is roi shift
            shiftx = int(shiftx)
            shifty = int(shifty)
            roi.left = roi.left + shiftx - expand_pixel - alignx
            roi.top = roi.top + shifty - expand_pixel - aligny
            roi.right = roi.right + shiftx - expand_pixel - alignx
            roi.bottom = roi.bottom + shifty - expand_pixel - aligny
            roi.tofile(outfilename)
        img_ori = draw_roi_onimage(roi2, img_ori)
        imgs.append(np.array(img_ori, dtype=np.uint16))
    else:
        progress.setValue(num)
        QMessageBox.information(widget, "提示", "操作成功")
    # write roi and image merge
    tif = TiffWriter(mergefile)
    for img in imgs:
        tif.write(img, contiguous=True)
    tif.close()
    # write batch txt for caculate roi
    with open(tifroifile, "w") as f:
        for imagefile, outname in zip(imagelist, outlist):
            outfilename = outname + "_shift.zip"
            f.write(imagefile + "\n")
            f.write(outfilename + "\n")
Example #4
0
def write_tiff(filepath: str, img: ndarray) -> None:
    """Write the image to a tiff file."""
    tw = TiffWriter(filepath)
    tw.write(img)
Example #5
0
    def event(self, doc):
        '''Add event document information to a ".tiff" file.

        This method adds event document information to a ".tiff" file,
        creating it if necessary.

        .. warning::

            All non 2D 'image-like' data is explicitly ignored.

        .. note::

            The data in Events might be structured as an Event, an EventPage,
            or a "bulk event" (deprecated). The DocumentRouter base class takes
            care of first transforming the other representations into an
            EventPage and then routing them through here, as we require Event
            documents _in this case_ we overwrite both the `event` method and
            the `event_page` method so we can assume we will always receive an
            Event.

        Parameters:
        -----------
        doc : dict
            Event document
        '''
        event_model.verify_filled(event_model.pack_event_page(*[doc]))
        descriptor = self._descriptors[doc['descriptor']]
        stream_name = descriptor.get('name')
        for field in doc['data']:
            img = doc['data'][field]
            # Check that the data is 2D or 3D; if not ignore it.
            data_key = descriptor['data_keys'][field]
            ndim = len(data_key['shape'] or [])
            if data_key['dtype'] == 'array' and 1 < ndim < 4:
                img_asarray = numpy.asarray(img, dtype=self._astype)
                if tuple(data_key['shape']) != img_asarray.shape:
                    warnings.warn(
                        f"The descriptor claims the data shape is {data_key['shape']} "
                        f"but the data is actual data shape is {img_asarray.shape}! "
                        f"This will be an error in the future.")
                    ndim = img_asarray.ndim

                if ndim == 2:
                    # handle 2D data just like 3D data
                    # by adding a 3rd dimension
                    img_asarray = numpy.expand_dims(img_asarray, axis=0)
                for i in range(img_asarray.shape[0]):
                    img_asarray_2d = img_asarray[i, :]
                    num = next(self._counter[stream_name][field])
                    filename = get_prefixed_filename(
                        file_prefix=self._file_prefix,
                        start_doc=self._start,
                        descriptor_doc=descriptor,
                        event_doc=doc,
                        num=num,
                        stream_name=stream_name,
                        field=field,
                        pad=self._event_num_pad)
                    fname = self._manager.reserve_name('stream_data', filename)
                    Path(fname).parent.mkdir(parents=True, exist_ok=True)
                    tw = TiffWriter(fname, **self._init_kwargs)
                    self._tiff_writers[stream_name][field + f'-{num}'] = tw
                    tw.write(img_asarray_2d, *self._kwargs)
Example #6
0
    def event_page(self, doc):
        '''Add event page document information to a ".tiff" file.

        This method adds event_page document information to a ".tiff" file,
        creating it if nesecary.

        .. warning::

            All non 2D 'image like' data is explicitly ignored.

        .. note::

            The data in Events might be structured as an Event, an EventPage,
            or a "bulk event" (deprecated). The DocumentRouter base class takes
            care of first transforming the other representations into an
            EventPage and then routing them through here, so no further action
            is required in this class. We can assume we will always receive an
            EventPage.

        Parameters:
        -----------
        doc : dict
            EventPage document
        '''
        event_model.verify_filled(doc)
        descriptor = self._descriptors[doc['descriptor']]
        stream_name = descriptor.get('name')
        for field in doc['data']:
            for img in doc['data'][field]:
                # Check that the data is 2D or 3D; if not ignore it.
                data_key = descriptor['data_keys'][field]
                ndim = len(data_key['shape'] or [])
                if data_key['dtype'] == 'array' and 1 < ndim < 4:
                    # there is data to be written so
                    # create a file for this stream and field
                    # if one does not exist yet
                    if not self._tiff_writers.get(stream_name, {}).get(field):
                        filename = get_prefixed_filename(
                            file_prefix=self._file_prefix,
                            start_doc=self._start,
                            stream_name=stream_name,
                            field=field)
                        fname = self._manager.reserve_name(
                            'stream_data', filename)
                        Path(fname).parent.mkdir(parents=True, exist_ok=True)
                        tw = TiffWriter(fname, **self._init_kwargs)
                        self._tiff_writers[stream_name][field] = tw

                    # write the data
                    img_asarray = numpy.asarray(img, dtype=self._astype)
                    if ndim == 2:
                        # handle 2D data just like 3D data
                        # by adding a 3rd dimension
                        img_asarray = numpy.expand_dims(img_asarray, axis=0)
                    for i in range(img_asarray.shape[0]):
                        img_asarray_2d = img_asarray[i, :]
                        # append the image to the file
                        tw = self._tiff_writers[stream_name][field]
                        tw.write(img_asarray_2d,
                                 contiguous=True,
                                 *self._kwargs)