Пример #1
0
def main():
    c = Calibration()
    c.parse()
    c.read_pixelsSize()
    c.preprocess()
    c.gui_peakPicker()
    six.moves.input("Press enter to quit")
Пример #2
0
def _collect_img(exposure,
                 dark_sub_bool,
                 sample_md,
                 tag,
                 RE_instance,
                 *,
                 calibrant=None,
                 detector=None):
    """helper function to collect image and return it"""
    # grab beamtime object linked to run_engine
    bto = RE_instance.beamtime
    plan = ScanPlan(bto, ct, exposure).factory()
    sample_md.update(bto)

    if tag == "calib":
        # instantiate Calibrant class
        calibrant_obj = Calibration(calibrant=calibrant).calibrant
        if calibrant_obj is None:
            raise xpdAcqException("Invalid calibrant")
        dSpacing = calibrant_obj.dSpacing
        if not dSpacing:
            raise xpdAcqException("empty dSpacing from calibrant")
        sample_md.update({"dSpacing": dSpacing, "detector": detector})
        plan = bpp.msg_mutator(plan, _inject_calibration_tag)

    # collect image
    uid = RE_instance(sample_md, plan)
    # last one must be light
    db = xpd_configuration["db"]
    light_header = db[uid[-1]]
    dark_uid = light_header["start"].get("sc_dk_field_uid")
    dark_header = db[dark_uid]
    dark_img = dark_header.data(glbl["image_field"])
    dark_img = np.asarray(next(dark_img)).squeeze()
    img = light_header.data(glbl["image_field"])
    img = np.asarray(next(img)).squeeze()

    if dark_sub_bool:
        img -= dark_img
    # FIXME: filename template from xpdAn
    fn_template = "from_calib_func_{}.poni".format(_timestampstr(time.time()))

    return img, fn_template
Пример #3
0
def test_load_calibrant(fresh_xrun, bt):
    xrun = fresh_xrun
    xrun.beamtime = bt
    # pyfai factory
    for k, calibrant_obj in CALIBRANT_FACTORY.items():
        # light weight callback
        def check_eq(name, doc):
            assert calibrant_obj.dSpacing == doc["dSpacing"]
            assert k == doc["sample_name"]

        t = xrun.subscribe(check_eq, "start")
        # execute
        run_calibration(calibrant=k, phase_info=k, RE_instance=xrun)
        # clean
        xrun.unsubscribe(t)
    # invalid calibrant
    with pytest.raises(xpdAcqException):
        run_calibration(calibrant="pyFAI",
                        phase_info="buggy",
                        RE_instance=xrun)
    # filepath
    pytest_dir = rs_fn("xpdacq", "tests/")
    src = os.path.join(pytest_dir, "Ni24.D")
    dst_base = os.path.abspath(str(uuid.uuid4()))
    os.makedirs(dst_base)
    fn = str(uuid.uuid4())
    dst = os.path.join(dst_base, fn + ".D")
    shutil.copy(src, dst)
    c = Calibration(calibrant=dst)

    def check_eq(name, doc):
        assert c.calibrant.dSpacing == doc["dSpacing"]
        assert dst == doc["sample_name"]

    t = xrun.subscribe(check_eq, "start")
    # execute
    run_calibration(calibrant=dst, phase_info="buggy", RE_instance=xrun)
    # clean
    xrun.unsubscribe(t)
Пример #4
0
def img_calibration(img,
                    wavelength,
                    calibrant="Ni",
                    detector="perkin_elmer",
                    calib_ref_fp=None,
                    **kwargs):
    """Function to calibrate experimental geometry for an image

    Parameters
    ----------
    img : ndarray
        2D powder diffraction image from calibrant
    wavelength : float
        x-ray wavelength in angstrom.
    calibrant : str, optional
        calibrant being used, default is 'Ni'.
        input could be "full file path" to customized d-spacing file with
        ".D" extension or one of pre-defined calibrant names.
        List of pre-defined calibrant names:
        ['NaCl', 'AgBh', 'quartz', 'Si_SRM640', 'Ni', 'Si_SRM640d',
        'Si_SRM640a', 'alpha_Al2O3', 'LaB6_SRM660b', 'TiO2', 'CrOx',
        'LaB6_SRM660c', 'CeO2', 'Si_SRM640c', 'CuO', 'Si_SRM640e',
        'PBBA', 'ZnO', 'Si', 'C14H30O', 'cristobaltite', 'LaB6_SRM660a',
        'Au', 'Cr2O3', 'Si_SRM640b', 'LaB6', 'Al', 'mock']
    detector : str or pyFAI.detector.Detector instance, optional.
        detector used to collect data. default value is 'perkin-elmer'.
        other allowed values are in pyFAI documentation.
    calib_ref_fp : str, optional
        full file path to where the native pyFAI calibration information
        will be saved. Default to current working directory.
    kwargs:
        Additional keyword argument for calibration. please refer to
        pyFAI documentation for all options.

    Returns
    -------
    ai : pyFAI.AzimuthalIntegrator
        instance of AzimuthalIntegrator. Can be used to integrate 2D
        images directly.

    Examples
    --------
    calib Ni image with pyFAI default ``Ni.D`` d-spacing
    with wavlength 0.1823 angstrom

    >>> import tifffile as tif
    >>> ni_img = tif.imread('<path_to_img_file>')
    >>> ai = img_calibration(ni_img, 0.1823)

    calib Ni image with pyFAI customized ``myNi.D`` d-spacing
    with wavlength 0.1823 angstrom

    >>> import tifffile as tif
    >>> ni_img = tif.imread('<path_to_img_file>')
    >>> ai = img_calibration(ni_img, 0.1823, 'path/to/myNi.D')

    integrate image right after calibration

    >>> import matplotlib.pyplot as plt
    >>> npt = 1482 # just a number for demonstration
    >>> q, Iq = ai.integrate1d(ni_img, npt, unit="q_nm^-1")
    >>> plt.plot(q, Iq)

    References
    ---------
    pyFAI documentation:
    http://pyfai.readthedocs.io/en/latest/
    """
    from pyFAI.calibration import Calibration, Calibrant

    wavelength *= 10**-10
    if isinstance(calibrant, list):
        calibrant = Calibrant(dSpacing=calibrant, wavelength=wavelength)
    # configure calibration instance
    c = Calibration(calibrant=calibrant,
                    detector=detector,
                    wavelength=wavelength)
    # pyFAI calibration
    calib_c, timestr = _calibration(img, c, calib_ref_fp, **kwargs)
    # TODO: apply polarization correction and recalibrate?

    return calib_c, calib_c.ai
Пример #5
0
def run_calibration(exposure=5,
                    dark_sub_bool=True,
                    calibrant=None,
                    phase_info=None,
                    wavelength=None,
                    detector=None,
                    *,
                    RE_instance=None,
                    parallel=True,
                    **kwargs):
    """function to run entire calibration process.

    Entire process includes:

    1. collect calibration image,

    2. trigger pyFAI interactive calibration process,

    3. store calibration parameters as a yaml file

    calibration parameters will be saved under xpdUser/config_base/
    and this set of parameters will be injected as metadata to
    subsequent scans until you perform this process again

    Parameters
    ----------
    exposure : int, optional
        total exposure time in sec. default is 5s
    dark_sub_bool : bool, optional
        option of turn on/off dark subtraction on this calibration
        image. default is True.
    calibrant : str, optional
        calibrant being used, default is 'Ni'.
        input could be full file path to customized d-spacing file with
        ".D" extension or one of pre-defined calibrant names.
        List of pre-defined calibrant names is:
        ['NaCl', 'AgBh', 'quartz', 'Si_SRM640', 'Ni', 'Si_SRM640d',
        'Si_SRM640a', 'alpha_Al2O3', 'LaB6_SRM660b', 'TiO2', 'CrOx',
        'LaB6_SRM660c', 'CeO2', 'Si_SRM640c', 'CuO', 'Si_SRM640e',
        'PBBA', 'ZnO', 'Si', 'C14H30O', 'cristobaltite', 'LaB6_SRM660a',
        'Au', 'Cr2O3', 'Si_SRM640b', 'LaB6', 'Al', 'mock']
    phase_info : str, optional
        phase infomation of calibrant, which is required to data
        reduction process. This field will be parsed with the same logic
        as the one used in parsing spreadsheet information. For detailed
        information, please visit:
        http://xpdacq.github.io/usb_Running.html#phase-string
        If both ``calibrant`` and ``phase_info`` arguments are not provided,
        this field will be defaulted to ``Ni``.
    wavelength : float, optional
        x-ray wavelength in angstrom. default to value stored in
        existing Beamtime object
    detector : str or pyFAI.detector.Detector instance, optional.
        detector used to collect data. default value is 'perkin-elmer'.
        other allowed values are in pyFAI documentation.
    RE_instance : bluesky.run_engine.RunEngine instance, optional
        instance of run engine. Default is xrun. Do not change under
        normal circumstances.
    parallel : bool, optional
        Tag for whether run the calibration step in a separte
        process. Running in parallel in principle yields better resource
        allocation. Default is ``True``, only change to ``False`` if
        error is raised.
    kwargs:
        Additional keyword argument for calibration. please refer to
        pyFAI documentation for all options.

    Note
    ----
    Details about peak-picking gui from pyFAI documentaion

      http://pyfai.readthedocs.io/en/latest/usage/cookbook/calibrate.html#start-pyfai-calibration_md
    """
    # default information
    if detector is None:
        detector = "perkin_elmer"
    sample_md = _sample_name_phase_info_configuration(calibrant, phase_info,
                                                      "calib")
    if calibrant is None:
        calibrant = os.path.join(glbl["usrAnalysis_dir"], "Ni24.D")

    # collect & pull subtracted image
    if RE_instance is None:
        xrun_name = _REQUIRED_OBJ_LIST[0]
        RE_instance = _check_obj(xrun_name)  # will raise error if not exists
    img, fn_template = _collect_img(
        exposure,
        dark_sub_bool,
        sample_md,
        "calib",
        RE_instance,
        detector=detector,
        calibrant=calibrant,
    )
    print("INFO: Please navigate to the analysis terminal to complete "
          "the interactive calibration process.\nYou may find the "
          "the analysis terminal similar to data acquisition terminal"
          "(current terminal) except there is information about the "
          "analysis pipeline printed")
    print("INFO: For a quick guide on the interactive calibration "
          "process, please visit our web-doc at:\n"
          "https://xpdacq.github.io/xpdAcq/usb_Running.html#calib-manual\n")

    if not parallel:  # backup when pipeline fails
        # get wavelength from bt
        if wavelength is None:
            bt_fp = os.path.join(glbl["yaml_dir"], "bt_bt.yml")
            if not os.path.isfile(bt_fp):
                raise FileNotFoundError("Can't find your Beamtime yaml file.\n"
                                        "Did you accidentally delete it? "
                                        "Please contact beamline staff "
                                        "ASAP")
            bto = Beamtime.from_yaml(open(bt_fp))
            wavelength = float(bto.wavelength) * 10**(-10)
        # configure calibration instance
        c = Calibration(calibrant=calibrant,
                        detector=detector,
                        wavelength=wavelength)
        # pyFAI calibration
        calib_c, timestr = _calibration(img, c, fn_template, **kwargs)
        assert calib_c.calibrant.wavelength == wavelength
        # save param for xpdAcq
        yaml_name = glbl["calib_config_name"]
        calib_yml_fp = os.path.join(glbl["config_base"],
                                    glbl["calib_config_name"])
        _save_calib_param(calib_c, timestr, calib_yml_fp)
Пример #6
0
def calibration(img, calibrant_file=None, wavelength=None,
                calib_collection_uid=None, save_file_name=None,
                detector=None, gaussian=None):
    """ run calibration process on a image with geometry correction
    software

    current backend is ``pyFAI``.

    Parameters
    ----------
    img : ndarray
        image to be calibrated
    calibrant_file : str, optional
        calibrant file being used, default is 'Ni.D' under 
        xpdUser/userAnalysis/
    wavelength : flot, optional
        current of x-ray wavelength, in angstrom. Default value is 
        read out from existing xpdacq.Beamtime object
    calibration_collection_uid : str, optional
        uid of calibration collection. default is generated from run
        calibration
    save_file_name : str, optional
        file name for yaml that carries resultant calibration parameters
    detector : pyfai.detector.Detector, optional.
        instance of detector which defines pixel size in x- and
        y-direction. Default is set to Perkin Elmer detector
    gaussian : int, optional
        gaussian width between rings, Default is 100.
    """
    # default params
    interactive = True
    dist = 0.1

    _check_obj(_REQUIRED_OBJ_LIST)
    ips = get_ipython()
    bto = ips.ns_table['user_global']['bt']
    xrun = ips.ns_table['user_global']['xrun']

    calibrant = Calibrant()
    # d-spacing
    if calibrant_file is not None:
        calibrant.load_file(calibrant_file)
        calibrant_name = os.path.split(calibrant_file)[1]
        calibrant_name = os.path.splitext(calibrant_name)[0]
    else:
        calibrant.load_file(os.path.join(glbl.usrAnalysis_dir, 'Ni.D'))
        calibrant_name = 'Ni'
    # wavelength
    if wavelength is None:
        _wavelength = bto['bt_wavelength']
    else:
        _wavelength = wavelength
    calibrant.wavelength = _wavelength * 10 ** (-10)
    # detector
    if detector is None:
        detector = Perkin()
    # calibration
    timestr = _timestampstr(time.time())
    basename = '_'.join(['pyFAI_calib', calibrant_name, timestr])
    w_name = os.path.join(glbl.config_base, basename)  # poni name
    c = Calibration(wavelength=calibrant.wavelength,
                    detector=detector,
                    calibrant=calibrant,
                    gaussianWidth=gaussian)
    c.gui = interactive
    c.basename = w_name
    c.pointfile = w_name + ".npt"
    c.ai = AzimuthalIntegrator(dist=dist, detector=detector,
                               wavelength=calibrant.wavelength)
    c.peakPicker = PeakPicker(img, reconst=True, mask=detector.mask,
                              pointfile=c.pointfile, calibrant=calibrant,
                              wavelength=calibrant.wavelength)
    # method=method)
    if gaussian is not None:
        c.peakPicker.massif.setValleySize(gaussian)
    else:
        c.peakPicker.massif.initValleySize()

    if interactive:
        c.peakPicker.gui(log=True, maximize=True, pick=True)
        update_fig(c.peakPicker.fig)
    c.gui_peakPicker()
    c.ai.setPyFAI(**c.geoRef.getPyFAI())
    c.ai.wavelength = c.geoRef.wavelength

    return c.ai