示例#1
0
def outputFileName(group, subgroup, create_path = True):
    """generate the system default output data file name

    'Lattice/Year_Month/group/subgroup_Year_Month_Day_HourMinSec.hdf5'
    e.g. 'SR/2014_03/bpm/bpm_Fa_0_2014_03_04_145020.hdf5'

    if new directory is created, with permission "rwxrwxr-x"
    """
    # use the default file name
    import stat
    t0 = datetime.now()
    output_dir = ""
    for subdir in [machines.getOutputDir(), t0.strftime("%Y_%m"), group]:
        output_dir = os.path.join(output_dir, subdir)
        if not os.path.exists(output_dir):
            if create_path:
                _logger.info("creating new directory: {0}".format(output_dir))
                os.mkdir(output_dir)
                os.chmod(output_dir, stat.S_ISGID | stat.S_IRWXU | stat.S_IRWXG | \
                         stat.S_IROTH | stat.S_IXOTH)
            else:
                raise RuntimeError("{0} does not exist".format(output_dir))

    fopt = subgroup + t0.strftime("%Y_%m_%d_%H%M%S.hdf5")
    return os.path.join(output_dir, fopt)
示例#2
0
def outputFileName(group, subgroup, create_path=True):
    """generate the system default output data file name

    'Lattice/Year_Month/group/subgroup_Year_Month_Day_HourMinSec.hdf5'
    e.g. 'SR/2014_03/bpm/bpm_Fa_0_2014_03_04_145020.hdf5'

    if new directory is created, with permission "rwxrwxr-x"
    """
    # use the default file name
    import stat
    t0 = datetime.now()
    output_dir = ""
    for subdir in [machines.getOutputDir(), t0.strftime("%Y_%m"), group]:
        output_dir = os.path.join(output_dir, subdir)
        if not os.path.exists(output_dir):
            if create_path:
                _logger.info("creating new directory: {0}".format(output_dir))
                os.mkdir(output_dir)
                os.chmod(output_dir, stat.S_ISGID | stat.S_IRWXU | stat.S_IRWXG | \
                         stat.S_IROTH | stat.S_IXOTH)
            else:
                raise RuntimeError("{0} does not exist".format(output_dir))

    fopt = subgroup + t0.strftime("%Y_%m_%d_%H%M%S.hdf5")
    return os.path.join(output_dir, fopt)
示例#3
0
def measBrCaRmCol(kker, **kwargs):
    """measure the response matrix column between PVs (DC)

    kker - SP PV for corrector (waveform)
    waveform - "Fa" or "Tbt"
    timeout - 6 sec, EPICS CA timeout
    npoints - number of orbits for each kick.
    dxlst - a list of kick (raw unit), overwrite the choice of dxmax
    dxmax - range of kick [-dxmax, dxmax]
    ndx - default 4. Specify kicks in [-dxmax, dxmax].
    wait - default 1.5 second
    output - save the results
    verbose - default 0

    return the output file name. The output will be in HDF5 file format.
    """
    timeout = kwargs.pop("timeout", 6)
    wait = kwargs.pop("wait", 1.5)
    verbose = kwargs.pop("verbose", 0)
    npt = kwargs.pop("npoints", 4)
    wfm = kwargs.pop("waveform", "Fa")

    t0 = datetime.now()
    dxlst, x0 = [], np.array(caget(kker, timeout=timeout), 'd')
    if "dxlst" in kwargs:
        dxlst = kwargs.get("dxlst")
    elif "dxmax" in kwargs:
        dxmax = np.abs(kwargs.get("dxmax"))
        nx = kwargs.pop("ndx", 4)
        dxlst = list(np.linspace(-dxmax, dxmax, nx))
    else:
        raise RuntimeError("need input for at least of the parameters: "
                           "dxlst, xlst, dxmax")

    # use the provided filename or default datetimed filename
    output_file = kwargs.pop(
        "output",
        os.path.join(machines.getOutputDir(), t0.strftime("%Y_%m"), "orm",
                     t0.strftime("orm_%Y_%m_%d_%H%M%S.hdf5")))

    # save dx list
    h5f = h5py.File(output_file)
    grp = h5f.create_group(kker)
    grp.attrs["orm_t0"] = t0.strftime("%Y_%m_%d_%H:%M:%S.%f")
    grp["dxlst"] = dxlst
    h5f.close()

    # save the initial orbit
    getBrBpmData(waveform=wfm,
                 verbose=verbose - 1,
                 output_file=output_file,
                 h5group="%s/%s0" % (kker, wfm),
                 **kwargs)

    n1 = len(dxlst)
    for i, dx in enumerate(dxlst):
        if verbose > 0:
            print "%d/%d: Setting %s " % (i, n1, kker), dx
            sys.stdout.flush()
        try:
            nx0 = len(x0)
            xi = [x0i + dx for x0i in x0]
        except:
            # should never happen for booster
            xi = x0 + dx
        caput(kker, xi, wait=True, timeout=timeout)
        time.sleep(wait * 3)
        for j in range(npt):
            obt, fname = getBrBpmData(waveform=wfm,
                                      verbose=verbose - 1,
                                      output_file=output_file,
                                      h5group="%s/%s_dx%d__pt%d" %
                                      (kker, wfm, i, j),
                                      **kwargs)
            if verbose > 1:
                name, x, y, Is, ts, ddroffset = obt
                print "  %d/%d" % (j, npt), np.average(x[0]), np.std(x[0])
                sys.stdout.flush()
            time.sleep(wait)
        time.sleep(wait)

    caput(kker, x0, wait=True, timeout=timeout)

    t1 = datetime.now()

    h5f = h5py.File(output_file)
    h5f[kker].attrs["orm_t1"] = t1.strftime("%Y_%m_%d_%H:%M:%S.%f")
    h5f.close()
    return output_file
示例#4
0
def getBrBpmData(**kwargs):
    """
    timeout - 6sec
    sleep - 4sec
    output - True, use default file name, str - user specified filename

    returns name, x, y, Isum, timestamp, offset

    There will be warning if timestamp differs more than 1 second
    """
    trig_src = kwargs.get("trig", 0)
    verbose = kwargs.get("verbose", 0)
    waveform = kwargs.pop("waveform", "Tbt")
    name = kwargs.pop("name", "BPM")
    #timeout  = kwargs.get("timeout", 6)

    lat = machines.getLattice()
    if lat.name != "BR":
        raise RuntimeError("the current lattice is not 'BR': %s" % lat.name)

    t0 = datetime.now()

    pv_dcct = "BR-BI{DCCT:1}I-Wf"
    dcct1 = caget(pv_dcct, count=1000)

    pvpref = [
        bpm.pv(field="x")[0].replace("Pos:X-I", "")
        for bpm in getElements(name)
    ]
    names = [bpm.name for bpm in getElements(name)]

    if trig_src == 0 and waveform in ["Tbt", "Fa"]:
        ret = _brBpmTrigData(pvpref, waveform, **kwargs)
        x, y, Is, ts, offset = ret
    else:
        if waveform == "Tbt":
            pv_x = [pv + "TBT-X" for pv in pvpref]
            pv_y = [pv + "TBT-Y" for pv in pvpref]
            pv_S = [pv + "TBT-S" for pv in pvpref]
            pv_offset = [pv + "ddrTbtOffset" for pv in pvpref]
        elif waveform == "Fa":
            pv_x = [pv + "FA-X" for pv in pvpref]
            pv_y = [pv + "FA-Y" for pv in pvpref]
            pv_S = [pv + "FA-S" for pv in pvpref]
            pv_offset = [pv + "ddrFaOffset" for pv in pvpref]

        pv_ts = [pv + "TS:DdrTrigDate-I" for pv in pvpref]
        x = np.array(caget(pv_x), 'd')
        y = np.array(caget(pv_y), 'd')
        Is = np.array(caget(pv_S), 'd')
        ts = caget(pv_ts)
        offset = caget(pv_offset)

    # get dcct
    dcct2 = caget(pv_dcct, count=1000)
    t1 = datetime.now()

    data = (names, x, y, Is, ts, offset)

    if kwargs.get("output", None):
        # default output dir and file
        output_file = kwargs["output"]
        if output_file is True:
            # use the default file name
            output_dir = os.path.join(machines.getOutputDir(),
                                      t0.strftime("%Y_%m"), "bpm")
            if not os.path.exists(output_dir):
                os.makedirs(output_dir)
            fopt = "bpm_%s_%d_" % (waveform, trig_src) + \
                t0.strftime("%Y_%m_%d_%H%M%S.hdf5")
            output_file = os.path.join(output_dir, fopt)

        # save the data
        _saveBrBpmData(output_file,
                       waveform,
                       data,
                       h5group=kwargs.get("h5group", "/"),
                       dcct_data=(dcct1, dcct2),
                       ts=(t0, t1),
                       pvpref=pvpref)
        return data, output_file
    else:
        return data
示例#5
0
def getSrBpmData(**kwargs):
    """
    NSLS-II SR BPM data acquisition.

    Parameters
    -----------
    trig : int, optional
        Internal(0) or external(1) trigger.
    verbose : int
    waveform : str
        Waveform selection: ``"Tbt"``, ``"Fa"``
    bpms : list
        A list of BPM object.
    name : str
        BPM name or pattern, overwritten by parameter *bpms*
    count : int
        Waveform length. default all (0).
    output : str, True, False
        output file name, or default name (True), or no output (False).
    h5group : str
        output HDF5 group

    Returns
    --------
    name : list
        a list of BPM name
    x : array (nbpm, count)
        x orbit, shape (nbpm, waveform_length).
    y : array (nbpm, count)
        y orbit
    Isum : array (nbpm, count)
        Sum signal
    timestamp : list
    offset : list
        offset from the FPGA buffer.

    There will be warning if timestamp differs more than 1 second
    """
    trig_src = kwargs.get("trig", 0)
    verbose  = kwargs.get("verbose", 0)
    waveform = kwargs.pop("waveform", "Tbt")
    name     = kwargs.pop("bpms", kwargs.pop("name", "BPM"))
    count    = kwargs.get("count", 0)
    #timeout  = kwargs.get("timeout", 6)
    output   = kwargs.get("output", None)

    lat = machines.getLattice()
    if lat.name != "SR":
        raise RuntimeError("the current lattice is not 'BR': %s" % lat.name)

    t0 = datetime.now()

    #pv_dcct = "BR-BI{DCCT:1}I-Wf"
    #dcct1 = caget(pv_dcct, count=1000)
    elems = [e for e in getElements(name) if e.pv(field="x")]
    pvpref = [bpm.pv(field="x")[0].replace("Pos:XwUsrOff-Calc", "")
              for bpm in elems]
    names = [bpm.name for bpm in elems]

    if trig_src == 0 and waveform in ["Tbt", "Fa"]:
        # internal trig
        # ret = _srBpmTrigData(pvpref, waveform, **kwargs)
        # x, y, Is, ts, offset, xbbaofst, ybbaofst, extdata = ret
        x, y, Is, extdata = _srBpmTrigData(pvpref, waveform, **kwargs)
    else:
        if waveform == "Tbt":
            pv_x = [pv + "TBT-X" for pv in pvpref]
            pv_y = [pv + "TBT-Y" for pv in pvpref]
            pv_S = [pv + "TBT-S" for pv in pvpref]
            pv_offset = [pv + "ddrTbtOffset" for pv in pvpref]
        elif waveform == "Fa":
            pv_x = [pv + "FA-X" for pv in pvpref]
            pv_y = [pv + "FA-Y" for pv in pvpref]
            pv_S = [pv + "FA-S" for pv in pvpref]
            pv_offset = [pv + "ddrFaOffset" for pv in pvpref]

        pv_ts = [pv + "TS:DdrTrigDate-I" for pv in pvpref]
        pv_bbaxoff = [ pv + "BbaXOff-SP" for pv in pvpref]
        pv_bbayoff = [ pv + "BbaYOff-SP" for pv in pvpref]
        pv_evtcode = [ pv + "Trig:EventNo-I" for pv in pvpref]

        x  = caget(pv_x, count=count, throw=False)
        y  = caget(pv_y, count=count, throw=False)
        Is = caget(pv_S, count=count, throw=False)
        # check srBpmTrigData, key must agrees
        extdata = {
            "ddr_timestamp": np.array(caget(pv_ts)),
            "ddr_offset": np.array(caget(pv_offset), 'i'),
            "bba_xoffset": np.array(caget(pv_bbaxoff)),
            "bba_yoffset": np.array(caget(pv_bbayoff)),
            "event_code": np.array(caget(pv_evtcode))}
    # in case they have difference size
    d = []
    for v in [x, y, Is]:
        nx = max([len(r) for r in v if not isinstance(r, ca_nothing)])
        rec = np.zeros((len(v), nx), 'd')
        for i in range(len(v)):
            rec[i,:len(v[i])] = v[i]
        d.append(rec)
    x, y, Is = d
    # get dcct
    #dcct2 = caget(pv_dcct, count=1000)
    #t1 = datetime.now()

    data = (names, x, y, Is, extdata["ddr_timestamp"], extdata["ddr_offset"])

    if not output: return data
    
    if output is True:
        # use the default file name
        output_dir = os.path.join(machines.getOutputDir(),
                                  t0.strftime("%Y_%m"),
                                  "bpm")
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        fopt = "bpm_%s_%d_" % (waveform, trig_src) + \
            t0.strftime("%Y_%m_%d_%H%M%S.hdf5")
        output = os.path.join(output_dir, fopt)

    t1 = datetime.now()
    # save the data
    _saveSrBpmData(output, waveform, names, x, y, Is,
                   h5group=kwargs.get("h5group", "/"),
                   ts = (t0, t1),
                   pvpref = pvpref,
                   **extdata)
    return data, output
示例#6
0
def measBrCaRmCol(kker, **kwargs):
    """measure the response matrix column between PVs (DC)

    kker - SP PV for corrector (waveform)
    waveform - "Fa" or "Tbt"
    timeout - 6 sec, EPICS CA timeout
    npoints - number of orbits for each kick.
    dxlst - a list of kick (raw unit), overwrite the choice of dxmax
    dxmax - range of kick [-dxmax, dxmax]
    ndx - default 4. Specify kicks in [-dxmax, dxmax].
    wait - default 1.5 second
    output - save the results
    verbose - default 0

    return the output file name. The output will be in HDF5 file format.
    """
    timeout = kwargs.pop("timeout", 6)
    wait    = kwargs.pop("wait", 1.5)
    verbose = kwargs.pop("verbose", 0)
    npt     = kwargs.pop("npoints", 4)
    wfm     = kwargs.pop("waveform", "Fa")
    
    t0 = datetime.now()
    dxlst, x0 = [], np.array(caget(kker, timeout=timeout), 'd')
    if "dxlst" in kwargs:
        dxlst = kwargs.get("dxlst")
    elif "dxmax" in kwargs:
        dxmax = np.abs(kwargs.get("dxmax"))
        nx    = kwargs.pop("ndx", 4)
        dxlst = list(np.linspace(-dxmax, dxmax, nx))
    else:
        raise RuntimeError("need input for at least of the parameters: "
                           "dxlst, xlst, dxmax")

    # use the provided filename or default datetimed filename
    output_file = kwargs.pop(
        "output",
        os.path.join(machines.getOutputDir(),
                     t0.strftime("%Y_%m"),
                     "orm",
                     t0.strftime("orm_%Y_%m_%d_%H%M%S.hdf5")))

    # save dx list
    h5f = h5py.File(output_file)
    grp = h5f.create_group(kker)
    grp.attrs["orm_t0"] = t0.strftime("%Y_%m_%d_%H:%M:%S.%f")
    grp["dxlst"] = dxlst
    h5f.close()
    
    # save the initial orbit
    getBrBpmData(waveform=wfm,
                 verbose=verbose-1,
                 output_file=output_file,
                 h5group="%s/%s0" % (kker, wfm),
                 **kwargs)
    
    n1 = len(dxlst)
    for i,dx in enumerate(dxlst):
        if verbose > 0:
            print "%d/%d: Setting %s " % (i, n1, kker), dx
            sys.stdout.flush()
        try:
            nx0 = len(x0)
            xi = [x0i + dx for x0i in x0]
        except:
            # should never happen for booster
            xi = x0 + dx
        caput(kker, xi, wait=True, timeout=timeout)
        time.sleep(wait*3)
        for j in range(npt):
            obt, fname = getBrBpmData(
                waveform=wfm, verbose=verbose-1,
                output_file=output_file,
                h5group="%s/%s_dx%d__pt%d" % (kker, wfm, i, j),
                **kwargs)    
            if verbose > 1:
                name, x, y, Is, ts, ddroffset = obt
                print "  %d/%d" % (j,npt), np.average(x[0]), np.std(x[0])
                sys.stdout.flush()
            time.sleep(wait)
        time.sleep(wait)

    caput(kker, x0, wait=True, timeout=timeout)
    
    t1 = datetime.now()

    h5f = h5py.File(output_file)
    h5f[kker].attrs["orm_t1"] = t1.strftime("%Y_%m_%d_%H:%M:%S.%f")
    h5f.close()
    return output_file
示例#7
0
def getBrBpmData(**kwargs):
    """
    timeout - 6sec
    sleep - 4sec
    output - True, use default file name, str - user specified filename

    returns name, x, y, Isum, timestamp, offset

    There will be warning if timestamp differs more than 1 second
    """
    trig_src = kwargs.get("trig", 0)
    verbose  = kwargs.get("verbose", 0)
    waveform = kwargs.pop("waveform", "Tbt")
    name     = kwargs.pop("name", "BPM")
    #timeout  = kwargs.get("timeout", 6)

    lat = machines.getLattice()
    if lat.name != "BR":
        raise RuntimeError("the current lattice is not 'BR': %s" % lat.name)

    t0 = datetime.now()

    pv_dcct = "BR-BI{DCCT:1}I-Wf"
    dcct1 = caget(pv_dcct, count=1000)

    pvpref = [bpm.pv(field="x")[0].replace("Pos:X-I", "")
              for bpm in getElements(name)]
    names = [bpm.name for bpm in getElements(name)]

    if trig_src == 0 and waveform in ["Tbt", "Fa"]:
        ret = _brBpmTrigData(pvpref, waveform, **kwargs)
        x, y, Is, ts, offset = ret
    else:
        if waveform == "Tbt":
            pv_x = [pv + "TBT-X" for pv in pvpref]
            pv_y = [pv + "TBT-Y" for pv in pvpref]
            pv_S = [pv + "TBT-S" for pv in pvpref]
            pv_offset = [pv + "ddrTbtOffset" for pv in pvpref]
        elif waveform == "Fa":
            pv_x = [pv + "FA-X" for pv in pvpref]
            pv_y = [pv + "FA-Y" for pv in pvpref]
            pv_S = [pv + "FA-S" for pv in pvpref]
            pv_offset = [pv + "ddrFaOffset" for pv in pvpref]

        pv_ts = [pv + "TS:DdrTrigDate-I" for pv in pvpref]
        x  = np.array(caget(pv_x), 'd')
        y  = np.array(caget(pv_y), 'd') 
        Is = np.array(caget(pv_S), 'd')
        ts = caget(pv_ts)
        offset = caget(pv_offset)

    # get dcct
    dcct2 = caget(pv_dcct, count=1000)
    t1 = datetime.now()

    data = (names, x, y, Is, ts, offset)

    if kwargs.get("output", None):
        # default output dir and file
        output_file = kwargs["output"]
        if output_file is True:
            # use the default file name
            output_dir = os.path.join(machines.getOutputDir(),
                                      t0.strftime("%Y_%m"),
                                      "bpm")
            if not os.path.exists(output_dir):
                os.makedirs(output_dir)
            fopt = "bpm_%s_%d_" % (waveform, trig_src) + \
                t0.strftime("%Y_%m_%d_%H%M%S.hdf5")
            output_file = os.path.join(output_dir, fopt)

        # save the data
        _saveBrBpmData(output_file, waveform, data,
                       h5group=kwargs.get("h5group", "/"),
                       dcct_data = (dcct1, dcct2),
                       ts = (t0, t1),
                       pvpref = pvpref)
        return data, output_file
    else:
        return data
示例#8
0
def getSrBpmData(**kwargs):
    """
    NSLS-II SR BPM data acquisition.

    Parameters
    -----------
    trig : int, optional
        Internal(0) or external(1) trigger.
    verbose : int
    waveform : str
        Waveform selection: ``"Tbt"``, ``"Fa"``
    bpms : list
        A list of BPM object.
    name : str
        BPM name or pattern, overwritten by parameter *bpms*
    count : int
        Waveform length. default all (0).
    output : str, True, False
        output file name, or default name (True), or no output (False).
    h5group : str
        output HDF5 group

    Returns
    --------
    name : list
        a list of BPM name
    x : array (nbpm, count)
        x orbit, shape (nbpm, waveform_length).
    y : array (nbpm, count)
        y orbit
    Isum : array (nbpm, count)
        Sum signal
    timestamp : list
    offset : list
        offset from the FPGA buffer.

    There will be warning if timestamp differs more than 1 second
    """
    trig_src = kwargs.get("trig", 0)
    verbose = kwargs.get("verbose", 0)
    waveform = kwargs.pop("waveform", "Tbt")
    name = kwargs.pop("bpms", kwargs.pop("name", "BPM"))
    count = kwargs.get("count", 0)
    #timeout  = kwargs.get("timeout", 6)
    output = kwargs.get("output", None)

    lat = machines.getLattice()
    if lat.name != "SR":
        raise RuntimeError("the current lattice is not 'BR': %s" % lat.name)

    t0 = datetime.now()

    #pv_dcct = "BR-BI{DCCT:1}I-Wf"
    #dcct1 = caget(pv_dcct, count=1000)
    elems = [e for e in getElements(name) if e.pv(field="x")]
    pvpref = [
        bpm.pv(field="x")[0].replace("Pos:XwUsrOff-Calc", "") for bpm in elems
    ]
    names = [bpm.name for bpm in elems]

    if trig_src == 0 and waveform in ["Tbt", "Fa"]:
        # internal trig
        # ret = _srBpmTrigData(pvpref, waveform, **kwargs)
        # x, y, Is, ts, offset, xbbaofst, ybbaofst, extdata = ret
        x, y, Is, extdata = _srBpmTrigData(pvpref, waveform, **kwargs)
    else:
        if waveform == "Tbt":
            pv_x = [pv + "TBT-X" for pv in pvpref]
            pv_y = [pv + "TBT-Y" for pv in pvpref]
            pv_S = [pv + "TBT-S" for pv in pvpref]
            pv_offset = [pv + "ddrTbtOffset" for pv in pvpref]
        elif waveform == "Fa":
            pv_x = [pv + "FA-X" for pv in pvpref]
            pv_y = [pv + "FA-Y" for pv in pvpref]
            pv_S = [pv + "FA-S" for pv in pvpref]
            pv_offset = [pv + "ddrFaOffset" for pv in pvpref]

        pv_ts = [pv + "TS:DdrTrigDate-I" for pv in pvpref]
        pv_bbaxoff = [pv + "BbaXOff-SP" for pv in pvpref]
        pv_bbayoff = [pv + "BbaYOff-SP" for pv in pvpref]
        pv_evtcode = [pv + "Trig:EventNo-I" for pv in pvpref]

        x = caget(pv_x, count=count, throw=False)
        y = caget(pv_y, count=count, throw=False)
        Is = caget(pv_S, count=count, throw=False)
        # check srBpmTrigData, key must agrees
        extdata = {
            "ddr_timestamp": np.array(caget(pv_ts)),
            "ddr_offset": np.array(caget(pv_offset), 'i'),
            "bba_xoffset": np.array(caget(pv_bbaxoff)),
            "bba_yoffset": np.array(caget(pv_bbayoff)),
            "event_code": np.array(caget(pv_evtcode))
        }
    # in case they have difference size
    d = []
    for v in [x, y, Is]:
        nx = max([len(r) for r in v if not isinstance(r, ca_nothing)])
        rec = np.zeros((len(v), nx), 'd')
        for i in range(len(v)):
            rec[i, :len(v[i])] = v[i]
        d.append(rec)
    x, y, Is = d
    # get dcct
    #dcct2 = caget(pv_dcct, count=1000)
    #t1 = datetime.now()

    data = (names, x, y, Is, extdata["ddr_timestamp"], extdata["ddr_offset"])

    if not output: return data

    if output is True:
        # use the default file name
        output_dir = os.path.join(machines.getOutputDir(),
                                  t0.strftime("%Y_%m"), "bpm")
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        fopt = "bpm_%s_%d_" % (waveform, trig_src) + \
            t0.strftime("%Y_%m_%d_%H%M%S.hdf5")
        output = os.path.join(output_dir, fopt)

    t1 = datetime.now()
    # save the data
    _saveSrBpmData(output,
                   waveform,
                   names,
                   x,
                   y,
                   Is,
                   h5group=kwargs.get("h5group", "/"),
                   ts=(t0, t1),
                   pvpref=pvpref,
                   **extdata)
    return data, output