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
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
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")
def write_tiff(filepath: str, img: ndarray) -> None: """Write the image to a tiff file.""" tw = TiffWriter(filepath) tw.write(img)
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)
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)