diff --git a/plugins/bm29/common.py b/plugins/bm29/common.py index f452fed..39f34e8 100644 --- a/plugins/bm29/common.py +++ b/plugins/bm29/common.py @@ -11,7 +11,7 @@ __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "03/12/2024" +__date__ = "20/02/2025" __status__ = "development" version = "0.0.2" @@ -71,7 +71,9 @@ def get_integrator(keycache): ai = pyFAI.load(keycache.poni) ai.wavelength = 1e-10 * pyFAI.units.hc / keycache.energy if keycache.mask: - mask = numpy.logical_or(fabio.open(keycache.mask).data, ai.detector.mask).astype("int8") + with fabio.open(keycache.mask) as fimg: + fabio_mask = fimg.data + mask = numpy.logical_or(fabio_mask, ai.detector.mask).astype("int8") ai.detector.mask = mask shared_cache[keycache] = ai return ai diff --git a/plugins/bm29/ispyb.py b/plugins/bm29/ispyb.py index ea338d1..cbd4de4 100644 --- a/plugins/bm29/ispyb.py +++ b/plugins/bm29/ispyb.py @@ -105,16 +105,15 @@ def send_icat(self, proposal=None, beamline=None, sample=None, dataset=None, pat :param path: directory name where processed data are staying :param raw: directory name of the raw data (not the processed ones) :param data: dict with all data sent to ISpyB - """ tmp = self.gallery.strip("/").split("/") idx_process = [i for i,j in enumerate(tmp) if j.lower().startswith("process")][-1] - if tmp[idx_process] == "process": - assert idx_process>5 + if tmp[idx_process] == "processed": + assert idx_process>=6 if proposal is None: - proposal = tmp[idx_process-5] + proposal = tmp[idx_process-6] if beamline is None: - beamline = tmp[idx_process-4] + beamline = tmp[idx_process-5] if sample is None: sample = tmp[idx_process-2] if dataset is None: diff --git a/plugins/bm29/nexus.py b/plugins/bm29/nexus.py index 0f4b383..3978bf3 100644 --- a/plugins/bm29/nexus.py +++ b/plugins/bm29/nexus.py @@ -1,10 +1,10 @@ """Module for writing HDF5 in the Nexus style""" -__author__ = "Jerome Kieffer" +__author__ = "Jérôme Kieffer" __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "21/04/2022" +__date__ = "20/02/2025" __status__ = "production" __docformat__ = 'restructuredtext' @@ -13,6 +13,7 @@ import time import logging import h5py +import atexit logger = logging.getLogger(__name__) @@ -45,7 +46,7 @@ def from_isotime(text, use_tz=False): text = str(text) if len(text) < 19: logger.warning("Not a iso-time string: %s", text) - return None + return base = text[:19] if use_tz and len(text) == 25: sgn = 1 if text[:19] == "+" else -1 @@ -85,7 +86,10 @@ class Nexus: TODO: make it thread-safe !!! """ - def __init__(self, filename, mode=None, creator=None, timeout=None): + def __init__(self, filename, mode=None, + creator=None, + timeout=None, + start_time=None): """ Constructor @@ -93,6 +97,7 @@ def __init__(self, filename, mode=None, creator=None, timeout=None): :param mode: can be 'r', 'a', 'w', '+' .... :param creator: set as attr of the NXroot :param timeout: retry for that amount of time (in seconds) + :param start_time: set as attr of the NXroot """ self.filename = os.path.abspath(filename) self.mode = mode @@ -132,10 +137,10 @@ def __init__(self, filename, mode=None, creator=None, timeout=None): self.file_handle = None self.h5 = h5py.File(self.filename, mode=self.mode) self.to_close = [] - + atexit.register(self.close) if not pre_existing: self.h5.attrs["NX_class"] = "NXroot" - self.h5.attrs["file_time"] = get_isotime() + self.h5.attrs["file_time"] = get_isotime(start_time) self.h5.attrs["file_name"] = self.filename self.h5.attrs["HDF5_Version"] = h5py.version.hdf5_version self.h5.attrs["creator"] = creator or self.__class__.__name__ @@ -178,8 +183,7 @@ def get_entry(self, name): if isinstance(grp, h5py.Group) and \ ("start_time" in grp) and \ self.get_attr(grp, "NX_class") == "NXentry": - return grp - return None + return grp def get_entries(self): """ @@ -212,7 +216,8 @@ def find_detector(self, all=False): return result def new_entry(self, entry="entry", program_name="pyFAI", - title=None, force_time=None, force_name=False): + title="description of experiment", + force_time=None, force_name=False): """ Create a new entry diff --git a/plugins/id02/nexus.py b/plugins/id02/nexus.py index 033a4bf..3978bf3 100644 --- a/plugins/id02/nexus.py +++ b/plugins/id02/nexus.py @@ -4,7 +4,7 @@ __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "29/01/2024" +__date__ = "20/02/2025" __status__ = "production" __docformat__ = 'restructuredtext' @@ -13,6 +13,7 @@ import time import logging import h5py +import atexit logger = logging.getLogger(__name__) @@ -70,7 +71,7 @@ def is_hdf5(filename): return sig == signature -class Nexus(object): +class Nexus: """ Writer class to handle Nexus/HDF5 data @@ -85,13 +86,17 @@ class Nexus(object): TODO: make it thread-safe !!! """ - def __init__(self, filename, mode=None, creator=None, start_time=None): + def __init__(self, filename, mode=None, + creator=None, + timeout=None, + start_time=None): """ Constructor :param filename: name of the hdf5 file containing the nexus :param mode: can be 'r', 'a', 'w', '+' .... :param creator: set as attr of the NXroot + :param timeout: retry for that amount of time (in seconds) :param start_time: set as attr of the NXroot """ self.filename = os.path.abspath(filename) @@ -107,15 +112,33 @@ def __init__(self, filename, mode=None, creator=None, start_time=None): else: self.mode = "a" - if self.mode == "r" and h5py.version.version_tuple >= (2, 9): - self.file_handle = open(self.filename, mode=self.mode + "b") - self.h5 = h5py.File(self.file_handle, mode=self.mode) + if timeout: + end = time.perf_counter() + timeout + while time.perf_counter() < end : + try: + if self.mode == "r": + self.file_handle = open(self.filename, mode="rb") + self.h5 = h5py.File(self.file_handle, mode="r") + else: + self.file_handle = None + self.h5 = h5py.File(self.filename, mode=self.mode) + except OSError: + os.stat(os.path.dirname(self.filename)) + time.sleep(1) + else: + break + else: + raise OSError(f"Unable to open HDF5 file {self.filename}") else: - self.file_handle = None - self.h5 = h5py.File(self.filename, mode=self.mode) + if self.mode == "r": + self.file_handle = open(self.filename, mode=self.mode + "b") + self.h5 = h5py.File(self.file_handle, mode=self.mode) + else: + self.file_handle = None + self.h5 = h5py.File(self.filename, mode=self.mode) self.to_close = [] - - if not pre_existing or "w" in mode: + atexit.register(self.close) + if not pre_existing: self.h5.attrs["NX_class"] = "NXroot" self.h5.attrs["file_time"] = get_isotime(start_time) self.h5.attrs["file_name"] = self.filename @@ -143,6 +166,7 @@ def __exit__(self, *arg, **kwarg): self.close() def flush(self): + "write to disk" if self.h5: self.h5.flush() @@ -199,7 +223,7 @@ def new_entry(self, entry="entry", program_name="pyFAI", :param entry: name of the entry :param program_name: value of the field as string - :param title: value of the field as string + :param title: description of experiment as str :param force_time: enforce the start_time (as string!) :param force_name: force the entry name as such, without numerical suffix. :return: the corresponding HDF5 group @@ -211,7 +235,7 @@ def new_entry(self, entry="entry", program_name="pyFAI", entry_grp = self.h5.require_group(entry) self.h5.attrs["default"] = entry entry_grp.attrs["NX_class"] = "NXentry" - entry_grp["title"] = title + entry_grp["title"] = str(title) entry_grp["program_name"] = program_name if isinstance(force_time, str): entry_grp["start_time"] = force_time @@ -230,16 +254,18 @@ def new_instrument(self, entry="entry", instrument_name="id00",): # howto external link # myfile['ext link'] = h5py.ExternalLink("otherfile.hdf5", "/path/to/resource") - def new_class(self, grp, name, class_type="NXcollection"): + @staticmethod + def new_class(grp, name, class_type="NXcollection"): """ create a new sub-group with type class_type + :param grp: parent group :param name: name of the sub-group :param class_type: NeXus class name :return: subgroup created """ sub = grp.require_group(name) - sub.attrs["NX_class"] = class_type + sub.attrs["NX_class"] = str(class_type) return sub def new_detector(self, name="detector", entry="entry", subentry="pyFAI"): @@ -253,8 +279,8 @@ def new_detector(self, name="detector", entry="entry", subentry="pyFAI"): from . import __version__ as version entry_grp = self.new_entry(entry) pyFAI_grp = self.new_class(entry_grp, subentry, "NXsubentry") - pyFAI_grp["definition_local"] = "pyFAI" - pyFAI_grp["definition_local"].attrs["version"] = version + pyFAI_grp["definition_local"] = str("pyFAI") + pyFAI_grp["definition_local"].attrs["version"] = str(version) det_grp = self.new_class(pyFAI_grp, name, "NXdetector") return det_grp @@ -282,6 +308,21 @@ def get_data(self, grp, attr=None, value=None): self.get_attr(grp[name], attr) == value] return coll + def get_default_NXdata(self): + """Return the default plot configured in the nexus structure. + + :return: the group with the default plot or None if not found + """ + entry_name = self.h5.attrs.get("default") + if entry_name: + entry_grp = self.h5.get(entry_name) + nxdata_name = entry_grp.attrs.get("default") + if nxdata_name: + if nxdata_name.startswith("/"): + return self.h5.get(nxdata_name) + return entry_grp.get(nxdata_name) + return None + def deep_copy(self, name, obj, where="/", toplevel=None, excluded=None, overwrite=False): """ perform a deep copy: @@ -300,7 +341,7 @@ def deep_copy(self, name, obj, where="/", toplevel=None, excluded=None, overwrit if name not in toplevel: grp = toplevel.require_group(name) for k, v in obj.attrs.items(): - grp.attrs[k] = v + grp.attrs[k] = v elif isinstance(obj, h5py.Dataset): if name in toplevel: if overwrite: diff --git a/plugins/id02/single_detector.py b/plugins/id02/single_detector.py index ed7aca3..33dcb1f 100644 --- a/plugins/id02/single_detector.py +++ b/plugins/id02/single_detector.py @@ -8,7 +8,7 @@ __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "14/02/2024" +__date__ = "20/02/2025" __status__ = "development" __version__ = "0.9.3" @@ -371,20 +371,20 @@ def process(self): if self.flat_filename.endswith(".h5") or self.flat_filename.endswith(".nxs") or self.flat_filename.endswith(".hdf5"): flat = self.read_data(self.flat_filename) else: - flat_fabio = fabio.open(self.flat_filename) - flat = flat_fabio.data - dummy = flat_fabio.header.get("Dummy") - try: - dummy = float(dummy) - except: - self.log_error("Dummy value in mask is unconsistent %s" % dummy) - dummy = None - ddummy = flat_fabio.header.get("DDummy") - try: - ddummy = float(ddummy) - except: - self.log_error("DDummy value in mask is unconsitent %s" % ddummy) - ddummy = 0 + with fabio.open(self.flat_filename) as flat_fabio: + flat = flat_fabio.data + dummy = flat_fabio.header.get("Dummy") + try: + dummy = float(dummy) + except: + self.log_error("Dummy value in mask is unconsistent %s" % dummy) + dummy = None + ddummy = flat_fabio.header.get("DDummy") + try: + ddummy = float(ddummy) + except: + self.log_error("DDummy value in mask is unconsitent %s" % ddummy) + ddummy = 0 if flat.ndim == 3: self.flat = pyFAI.average.average_dark(flat, center_method="median") @@ -415,28 +415,27 @@ def process(self): self.mask_filename = self.input.get("regrouping_mask_filename") if isinstance(self.mask_filename, StringTypes) and os.path.exists(self.mask_filename): try: - mask_fabio = fabio.open(self.mask_filename) + with fabio.open(self.mask_filename) as mask_fabio: + dummy = mask_fabio.header.get("Dummy") + try: + dummy = float(dummy) + except: + self.log_error("Dummy value in mask is unconsitent %s" % dummy) + dummy = None + ddummy = mask_fabio.header.get("DDummy") + try: + ddummy = float(ddummy) + except: + self.log_error("DDummy value in mask is unconsitent %s" % ddummy) + ddummy = 0 + if ddummy: + local_mask = abs(mask_fabio.data - dummy) <= ddummy + else: + local_mask = mask_fabio.data == dummy + self.dummy = dummy + self.delta_dummy = ddummy except: local_mask = self.read_data(self.mask_filename) != 0 - else: # this is very ID02 specific !!!! - dummy = mask_fabio.header.get("Dummy") - try: - dummy = float(dummy) - except: - self.log_error("Dummy value in mask is unconsitent %s" % dummy) - dummy = None - ddummy = mask_fabio.header.get("DDummy") - try: - ddummy = float(ddummy) - except: - self.log_error("DDummy value in mask is unconsitent %s" % ddummy) - ddummy = 0 - if ddummy: - local_mask = abs(mask_fabio.data - dummy) <= ddummy - else: - local_mask = mask_fabio.data == dummy - self.dummy = dummy - self.delta_dummy = ddummy if local_mask.ndim == 3: local_mask = pyFAI.average.average_dark(local_mask, center_method="median") if (local_mask is not None) and (local_mask.shape != shape): diff --git a/plugins/id02/xpcs.py b/plugins/id02/xpcs.py index 5faef14..2fcbed3 100644 --- a/plugins/id02/xpcs.py +++ b/plugins/id02/xpcs.py @@ -7,7 +7,7 @@ __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "13/07/2021" +__date__ = "20/02/2025" __status__ = "development" __version__ = "0.1.1" @@ -174,20 +174,23 @@ def make_qmask(self): numberq = experiment_setup.get("numberq", (1 << 16) - 2) # we plan to store the qmask as uint16 if experiment_setup.get("q_mask"): - qmask = fabio.open(experiment_setup["q_mask"]).data + with fabio.open(experiment_setup["q_mask"]) as fimg: + qmask = fimg.data else: q_array = geometry.center_array(self.shape, unit=self.unit) detector_maskfile = detector_section.get("mask") if detector_maskfile and os.path.exists(detector_maskfile): - detector_mask = fabio.open(detector_maskfile).data + with fabio.open(detector_maskfile) as fimg: + detector_mask = fimg.data else: detector_mask = detector.mask if detector_mask is None: detector_mask = numpy.zeros(self.shape, dtype=numpy.int8) beamstop_maskfile = experiment_setup.get("beamstop_mask") if beamstop_maskfile and os.path.exists(beamstop_maskfile): - beamstop_mask = fabio.open(beamstop_maskfile).data + with fabio.open(beamstop_maskfile) as fimg: + beamstop_mask = fimg.data else: beamstop_mask = numpy.zeros(self.shape, dtype=numpy.int8) mask = numpy.logical_or(detector_mask, beamstop_mask) diff --git a/plugins/id15.py b/plugins/id15.py index 0eed41d..6afb2f3 100644 --- a/plugins/id15.py +++ b/plugins/id15.py @@ -11,7 +11,7 @@ __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "03/09/2020" +__date__ = "20/02/2025" __status__ = "development" version = "0.4.0" @@ -226,7 +226,8 @@ def setup(self, kwargs=None): self.unit = self.input.get("unit", self.unit) self.wavelength = self.input.get("wavelength", self.wavelength) if os.path.exists(self.input.get("mask", "")): - self.mask = fabio.open(self.input["mask"]).data + with fabio.open(self.input["mask"]) as fimg: + self.mask = fimg.data self.dummy = self.input.get("dummy", self.dummy) self.delta_dummy = self.input.get("delta_dummy", self.delta_dummy) if self.input.get("do_polarziation"): @@ -329,36 +330,36 @@ def prepare_raw_hdf5(self, filter_=None): kwfilter = {"compression": 32008, "compression_opts": (0, 2)} # enforce lz4 compression first_image = self.input_files[0] - fimg = fabio.open(first_image) - shape = fimg.data.shape - stack_shape = (len(self.input_files),) + shape - first_frame_timestamp = os.stat(first_image).st_ctime - - try: - self.raw_nxs = pyFAI.io.Nexus(self.save_raw, "a") - except IOError as error: - self.log_warning("invalid HDF5 file %s: remove and re-create!\n%s" % (self.save_raw, error)) - os.unlink(self.save_raw) - self.raw_nxs = pyFAI.io.Nexus(self.save_raw) - entry = self.raw_nxs.new_entry("entry", - program_name="dahu", - title="ID15.raw_data", - force_time=first_frame_timestamp, - force_name=True) - entry["program_name"].attrs["version"] = dahu_version - entry["plugin_name"] = numpy.string_(".".join((os.path.splitext(os.path.basename(__file__))[0], self.__class__.__name__))) - entry["plugin_name"].attrs["version"] = version - coll = self.raw_nxs.new_class(entry, "data", class_type="NXdata") - try: - self.raw_ds = coll.require_dataset(name="data", shape=stack_shape, - dtype=fimg.data.dtype, - chunks=(1,) + shape, - **kwfilter) - except Exception as error: - logger.error("Error in creating dataset, disabling compression:%s", error) - self.raw_ds = coll.require_dataset(name="data", shape=stack_shape, - dtype=fimg.data.dtype, - chunks=(1,) + shape) + with fabio.open(first_image) as fimg: + shape = fimg.data.shape + stack_shape = (len(self.input_files),) + shape + first_frame_timestamp = os.stat(first_image).st_ctime + + try: + self.raw_nxs = pyFAI.io.Nexus(self.save_raw, "a") + except IOError as error: + self.log_warning("invalid HDF5 file %s: remove and re-create!\n%s" % (self.save_raw, error)) + os.unlink(self.save_raw) + self.raw_nxs = pyFAI.io.Nexus(self.save_raw) + entry = self.raw_nxs.new_entry("entry", + program_name="dahu", + title="ID15.raw_data", + force_time=first_frame_timestamp, + force_name=True) + entry["program_name"].attrs["version"] = dahu_version + entry["plugin_name"] = numpy.string_(".".join((os.path.splitext(os.path.basename(__file__))[0], self.__class__.__name__))) + entry["plugin_name"].attrs["version"] = version + coll = self.raw_nxs.new_class(entry, "data", class_type="NXdata") + try: + self.raw_ds = coll.require_dataset(name="data", shape=stack_shape, + dtype=fimg.data.dtype, + chunks=(1,) + shape, + **kwfilter) + except Exception as error: + logger.error("Error in creating dataset, disabling compression:%s", error) + self.raw_ds = coll.require_dataset(name="data", shape=stack_shape, + dtype=fimg.data.dtype, + chunks=(1,) + shape) return self.raw_ds def save_result(self, out, I, sigma=None): diff --git a/plugins/id15v2.py b/plugins/id15v2.py index 1b24f29..0ebd23d 100644 --- a/plugins/id15v2.py +++ b/plugins/id15v2.py @@ -9,7 +9,7 @@ __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "03/09/2020" +__date__ = "20/02/2025" __status__ = "development" version = "0.5.0" @@ -137,7 +137,8 @@ def setup(self, kwargs=None): self.unit = self.input.get("unit", self.unit) self.wavelength = self.input.get("wavelength", self.wavelength) if os.path.exists(self.input.get("mask", "")): - self.mask = fabio.open(self.input["mask"]).data + with fabio.open(self.input["mask"]) as fimg: + self.mask = fimg.data self.dummy = self.input.get("dummy", self.dummy) self.delta_dummy = self.input.get("delta_dummy", self.delta_dummy) if self.input.get("do_polarziation"): @@ -210,7 +211,8 @@ def process(self): raw = cbf.read(fname, only_raw=True) data = bo(raw, as_float=False).get().reshape(shape) else: - data = fabio.open(fname).data + with fabio.open(fname) as fimg: + data = fimg.data if data is None: self.log_error("Failed reading file: %s" % self.input_files[idx], do_raise=False) diff --git a/plugins/id27.py b/plugins/id27.py index e9108b3..cce2693 100644 --- a/plugins/id27.py +++ b/plugins/id27.py @@ -331,7 +331,10 @@ def fabio_conversion(file_path, """ results = [] filename = os.path.join(file_path, scan_number, f'{detector}_????.h5') - files = {f:fabio.open(f).nframes for f in sorted(glob.glob(filename))} #since python 3.7 dict are ordered ! + files = {} #since python 3.7 dict are ordered ! + for f in sorted(glob.glob(filename)): + with fabio.open(f) as fimg: + files[f] = fimg.nframes all_single = max(files.values())==1 file_path = file_path.rstrip("/") @@ -353,24 +356,24 @@ def fabio_conversion(file_path, cnt = 0 for idx_file, filename in enumerate(files): - img_data_fabio = fabio.open(filename) - basename = folder if (len(files) == 1 or all_single) else f"{folder}_{idx_file+1:04d}" - - dest_dir2 = os.path.join(dest_dir, basename) - if not os.path.exists(dest_dir2): - with lock: - if not os.path.exists(dest_dir2): - os.makedirs(dest_dir2) - for i in range(img_data_fabio.nframes): - cnt += 1 - frame = img_data_fabio.getframe(i) - conv = frame.convert(fabioimage) - data = conv.data.astype('int32') - data[data < 0] = 0 - conv.data = data - output = os.path.join(dest_dir2, f"{dset_name}_{cnt if all_single else i+1:04d}.{extension}") - conv.write(output) - results.append(output) + with fabio.open(filename) as img_data_fabio: + basename = folder if (len(files) == 1 or all_single) else f"{folder}_{idx_file+1:04d}" + + dest_dir2 = os.path.join(dest_dir, basename) + if not os.path.exists(dest_dir2): + with lock: + if not os.path.exists(dest_dir2): + os.makedirs(dest_dir2) + for i in range(img_data_fabio.nframes): + cnt += 1 + frame = img_data_fabio.getframe(i) + conv = frame.convert(fabioimage) + data = conv.data.astype('int32') + data[data < 0] = 0 + conv.data = data + output = os.path.join(dest_dir2, f"{dset_name}_{cnt if all_single else i+1:04d}.{extension}") + conv.write(output) + results.append(output) if export_icat: metadata = {"definition": "conversion", "Sample_name": sample_name} diff --git a/plugins/id31/__init__.py b/plugins/id31/__init__.py index 301b8c7..a1a2ef5 100644 --- a/plugins/id31/__init__.py +++ b/plugins/id31/__init__.py @@ -12,7 +12,7 @@ __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "06/02/2020" +__date__ = "20/02/2025" __status__ = "development" version = "0.1.0" @@ -48,7 +48,8 @@ def integrate_simple(poni_file, image_file, curve_file, nbins=1000): :param nbins: number of output bins """ ai = pyFAI.load(poni_file) - img = fabio.open(image_file).data + with fabio.open(image_file) as fimg: + img = fimg.data ai.integrate1d(img, nbins, filename=curve_file, unit="2th_deg", method="splitpixel") return {"out_file": curve_file} plugin_from_function(integrate_simple) @@ -109,7 +110,8 @@ def setup(self, kwargs): json_path = self.input.get("json", "") if not os.path.exists(json_path): self.log_error("Integration setup file (JSON): %s does not exist" % json_path, do_raise=True) - self.json_data = json.load(open(json_path)) + with open(json_path) as fp: + self.json_data = json.load(fp) ai = make_ai(self.json_data) stored = self._ais.get(str(ai), ai) @@ -140,21 +142,21 @@ def process(self): continue basename = os.path.splitext(os.path.basename(fname))[0] destination = os.path.join(self.dest_dir, basename + ".dat") - fimg = fabio.open(fname) - if self.wavelength is not None: - monitor = self.getMon(fimg.header, self.wavelength) / self.norm - else: - monitor = 1.0 - self.ai.integrate1d(fimg.data, npt=self.npt, method=self.method, - safe=False, - filename=destination, - normalization_factor=monitor, - unit=self.unit, - dummy=self.dummy, - delta_dummy=self.delta_dummy, - polarization_factor=self.polarization_factor, - correctSolidAngle=self.do_SA - ) + with fabio.open(fname) as fimg: + if self.wavelength is not None: + monitor = self.getMon(fimg.header, self.wavelength) / self.norm + else: + monitor = 1.0 + self.ai.integrate1d(fimg.data, npt=self.npt, method=self.method, + safe=False, + filename=destination, + normalization_factor=monitor, + unit=self.unit, + dummy=self.dummy, + delta_dummy=self.delta_dummy, + polarization_factor=self.polarization_factor, + correctSolidAngle=self.do_SA + ) self.output_files.append(destination) def teardown(self): diff --git a/plugins/pyfai.py b/plugins/pyfai.py index 829929e..9306d5f 100755 --- a/plugins/pyfai.py +++ b/plugins/pyfai.py @@ -9,7 +9,7 @@ __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "03/09/2020" +__date__ = "20/02/2025" __status__ = "development" version = "0.3.0" @@ -30,11 +30,10 @@ except ImportError: logger.error("Failed to import Fabio: download and install it from pypi") -import pyFAI, fabio def integrate_simple(poni_file, image_file, curve_file): ai = pyFAI.load(poni_file) - img = fabio.open(image_file).data - ai.integrate1d(img, 1000, filename=curve_file, unit="2th_deg") + with fabio.open(image_file) as fimg: + ai.integrate1d(fimg.data, 1000, filename=curve_file, unit="2th_deg") return {"out_file":curve_file} from dahu.plugin import plugin_from_function diff --git a/src/dahu/__init__.py b/src/dahu/__init__.py index e09f977..a3a66ad 100644 --- a/src/dahu/__init__.py +++ b/src/dahu/__init__.py @@ -33,7 +33,7 @@ __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "22/02/2024" +__date__ = "03/02/2025" __status__ = "production" import os diff --git a/src/dahu/job.py b/src/dahu/job.py index e0548e0..f39b945 100644 --- a/src/dahu/job.py +++ b/src/dahu/job.py @@ -12,7 +12,7 @@ __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "08/10/2020" +__date__ = "20/02/2025" __status__ = "production" from threading import Thread, Semaphore @@ -336,7 +336,8 @@ def input_data(self): """ with self._sem: if self.data_on_disk: - return json.load(open(self.data_on_disk + ".inp")) + with open(self.data_on_disk + ".inp") as fp: + return json.load(fp) else: return self._input_data @@ -350,7 +351,8 @@ def output_data(self): with self._sem: if self._status in [self.STATE_SUCCESS, self.STATE_FAILURE, self.STATE_ABORTED]: if self.data_on_disk: - return json.load(open(self.data_on_disk + ".out")) + with open(self.data_on_disk + ".out") as fp: + return json.load(fp) else: return self._output_data else: @@ -483,7 +485,8 @@ def getDataOutputFromId(cls, jobId, as_JSON=False): if job is not None: with job._sem: if job.data_on_disk: - data = open(job.data_on_disk + ".out").read() + with open(job.data_on_disk + ".out") as fp: + data = fp.read() if as_JSON: output = data else: @@ -518,7 +521,8 @@ def getDataInputFromId(cls, jobId, as_JSON=False): if job is not None: with job._sem: if job.data_on_disk: - data = open(job.data_on_disk + ".inp").read() + with open(job.data_on_disk + ".inp") as fp: + data = fp.read() if as_JSON: output = data else: diff --git a/version.py b/version.py index dc61048..62934b4 100755 --- a/version.py +++ b/version.py @@ -58,8 +58,8 @@ "rc": 12, "final": 15} -MAJOR = 2024 -MINOR = 12 +MAJOR = 2025 +MINOR = 2 MICRO = 0 RELEV = "final" # <16 SERIAL = 0 # <16