예제 #1
0
def acquire_pulses(filelist,
                   template,
                   noisepsd,
                   tracelength,
                   thresh,
                   nchan=2,
                   trigtemplate=None,
                   trigthresh=None,
                   positivepulses=True,
                   iotype="stanford",
                   savepath=None,
                   savename=None,
                   dumpnum=1,
                   maxevts=1000,
                   lgcoverlap=True,
                   convtoamps=1 / 1024):
    """
    Function for running the continuous trigger on many different files and saving the events 
    to .npz files for later processing.
    
    Parameters
    ----------
    filelist : list of strings
        List of files to be opened to take random sections from (should be full paths)
    template : ndarray
        The pulse template to be used when creating the optimum filter (assumed to be normalized)
    noisepsd : ndarray
        The two-sided power spectral density in units of A^2/Hz
    tracelength : int
        The desired trace length (in bins) to be saved when triggering on events.
    thresh : float
        The number of standard deviations of the energy resolution to use as the threshold for which events
        will be detected as a pulse.
    trigtemplate : NoneType, ndarray, optional
        The template for the trigger channel pulse. If left as None, then the trigger channel will not
        be analyzed.
    trigthresh : NoneType, float, optional
        The threshold value (in units of the trigger channel) such that any amplitudes higher than this will be 
        detected as ttl trigger event. If left as None, then only the pulses are analyzed.
    positivepulses : boolean, optional
        Boolean flag for which direction the pulses go in the traces. If they go in the positive direction, 
        then this should be set to True. If they go in the negative direction, then this should be set to False.
        Default is True.
    iotype : string, optional
        Type of file to open, uses a different IO function. Default is "stanford".
            "stanford" : Use qetpy.io.loadstanfordfile to open the files
    savepath : NoneType, str, optional
        Path to save the events to, if saveevents is True. If this is left as None, then they will
        be saved in the current working directory.
    savename : NoneType, str, optional
        Filename to save the events as. It is recommended that this follows CDMS format, which is 
        "[code][lasttwodigitsofyear][month][day]_[24hourclocktime]". If this is left as None, then 
        a dummy filename is used based on the inputted filelist.
    dumpnum : int, optional
        The dump number that the file should start saving from and the event number should be 
        determined by when saving. Default is 1.
    maxevts : int, optional
        The maximum number of events that should be stored in each dump when saving. Default
        is 1000.
    lgcoverlap : bool, optional
            If False, in eventtrigger skip events that overlap, based on tracelength, with the previous event.
    convtoamps : float, optional
        Correction factor to convert the data to Amps. The traces are multiplied by this
        factor, as is the TTL channel (if it exists). Default is 1/1024.
            
    """

    if savepath is None or not savepath:
        savepath = "./"

    if not savepath.endswith("/"):
        savepath += "/"

    if savename is None:
        now = datetime.datetime.now()
        savename = now.strftime("%Y%m%d_%H%M")

    if isinstance(filelist, str):
        filelist = [filelist]

    pulsetimes = np.zeros(maxevts)
    pulseamps = np.zeros(maxevts)
    trigtimes = np.zeros(maxevts)
    trigamps = np.zeros(maxevts)
    evttraces = np.zeros((maxevts, nchan, tracelength))
    trigtypes = np.zeros((maxevts, 3), dtype=bool)

    evt_counter = 0

    for f in filelist:

        if iotype == "stanford":
            traces, times, fs, trig = io.loadstanfordfile(
                f, convtoamps=convtoamps)
            if trigtemplate is None:
                trig = None
        else:
            raise ValueError("Unrecognized iotype inputted.")

        filt = OptimumFilt(fs,
                           template,
                           noisepsd,
                           tracelength,
                           trigtemplate=trigtemplate,
                           lgcoverlap=lgcoverlap)
        filt.filtertraces(traces, times, trig=trig)
        filt.eventtrigger(thresh,
                          trigthresh=trigthresh,
                          positivepulses=positivepulses)

        numevts = len(filt.pulsetimes)

        evt_counter += numevts

        if evt_counter < maxevts:

            pulsetimes[evt_counter - numevts:evt_counter] = filt.pulsetimes
            pulseamps[evt_counter - numevts:evt_counter] = filt.pulseamps
            trigtimes[evt_counter - numevts:evt_counter] = filt.trigtimes
            trigamps[evt_counter - numevts:evt_counter] = filt.trigamps
            evttraces[evt_counter - numevts:evt_counter] = filt.evttraces
            trigtypes[evt_counter - numevts:evt_counter] = filt.trigtypes

        elif evt_counter >= maxevts:
            numextra = evt_counter - maxevts
            numtoadd = maxevts - (evt_counter - numevts)

            pulsetimes[evt_counter - numevts:] = filt.pulsetimes[:numtoadd]
            pulseamps[evt_counter - numevts:] = filt.pulseamps[:numtoadd]
            trigtimes[evt_counter - numevts:] = filt.trigtimes[:numtoadd]
            trigamps[evt_counter - numevts:] = filt.trigamps[:numtoadd]
            evttraces[evt_counter - numevts:] = filt.evttraces[:numtoadd]
            trigtypes[evt_counter - numevts:] = filt.trigtypes[:numtoadd]

            for ii in range(numextra // maxevts + 1):

                io.saveevents_npz(pulsetimes=pulsetimes,
                                  pulseamps=pulseamps,
                                  trigtimes=trigtimes,
                                  trigamps=trigamps,
                                  traces=evttraces,
                                  trigtypes=trigtypes,
                                  savepath=savepath,
                                  savename=savename,
                                  dumpnum=dumpnum)
                dumpnum += 1

                pulsetimes.fill(0)
                pulseamps.fill(0)
                trigtimes.fill(0)
                trigamps.fill(0)
                evttraces.fill(0)
                trigtypes.fill(0)

                numleft = numevts - (numtoadd + ii * maxevts)

                if numleft > maxevts:
                    numleft = maxevts

                if numleft > 0:
                    pulsetimes[:numleft] = filt.pulsetimes[numtoadd + ii *
                                                           maxevts:numtoadd +
                                                           ii * maxevts +
                                                           numleft]
                    pulseamps[:numleft] = filt.pulseamps[numtoadd + ii *
                                                         maxevts:numtoadd +
                                                         ii * maxevts +
                                                         numleft]
                    trigtimes[:numleft] = filt.trigtimes[numtoadd + ii *
                                                         maxevts:numtoadd +
                                                         ii * maxevts +
                                                         numleft]
                    trigamps[:numleft] = filt.trigamps[numtoadd +
                                                       ii * maxevts:numtoadd +
                                                       ii * maxevts + numleft]
                    evttraces[:numleft] = filt.evttraces[numtoadd + ii *
                                                         maxevts:numtoadd +
                                                         ii * maxevts +
                                                         numleft]
                    trigtypes[:numleft] = filt.trigtypes[numtoadd + ii *
                                                         maxevts:numtoadd +
                                                         ii * maxevts +
                                                         numleft]

            evt_counter = np.sum((pulsetimes != 0) | (trigtimes != 0))

    # clean up the rest of the events
    if evt_counter > 0:
        io.saveevents_npz(pulsetimes=pulsetimes,
                          pulseamps=pulseamps,
                          trigtimes=trigtimes,
                          trigamps=trigamps,
                          traces=evttraces,
                          trigtypes=trigtypes,
                          savepath=savepath,
                          savename=savename,
                          dumpnum=dumpnum)
예제 #2
0
def _buildfakepulses_seg(rq,
                         cut,
                         templates,
                         amplitudes,
                         tdelay,
                         basepath,
                         taurises=None,
                         taufalls=None,
                         channels="PDS1",
                         relcal=None,
                         det="Z1",
                         convtoamps=1,
                         fs=625e3,
                         dumpnum=1,
                         filetype="mid.gz",
                         lgcsavefile=False,
                         savefilepath=None):
    """
    Hidden helper function for building fake pulses.

    Parameters
    ----------
    rq : pandas.DataFrame
        A pandas DataFrame object that contains all of the RQs for the dataset specified.
    cut : array_like
        A boolean array for the cut that selects the traces that will be loaded from the dump
        files. These traces serve as the underlying data to which a template is added.
    templates : ndarray, list of ndarray
        The template(s) to be added to the traces, assumed to be normalized to a max height
        of 1. The template start time should be centered on the center bin. If a list of templates,
        then each template will be added to the traces in succession, using the corresponding
        `amplitudes` and `tdelay`.
    amplitudes : ndarray, list of ndarray
        The amplitudes, in Amps, by which to scale the template to add to the traces. Must be
        same length as cut. A list of ndarray can be passed, where each ndarray corresponds to
        the amplitudes of the corresponding template in the list of templates.
    tdelay : ndarray, list of ndarray
        The time delay offset, in seconds, by which to shift the template to add to the traces.
        Bin interpolation is implemented for values that are not a multiple the reciprocal of
        the digitization rate. A list of ndarray can be passed, where each ndarray corresponds to
        the tdelays of the corresponding template in the list of templates.
    basepath : str
        The base path to the directory that contains the folders that the event dumps
        are in. The folders in this directory should be the series numbers.
    taurises : ndarray, list of ndarray, NoneType
        If specified, the rise times for the simulated pulses, in seconds. If left as None, then
        the `templates` argument is used.
    taufalls : ndarray, list of ndarray, NoneType
        If specified, the rise times for the simulated pulses, in seconds. If left as None, then
        the `templates` argument is used.
    channels : str, list of str, optional
        A list of strings that contains all of the channels that should be loaded. Only used if
        filetype=='mid.gz'.
    det : str, list of str, optional
        String or list of strings that specifies the detector name. Only used if
        filetype=='mid.gz'. If a list of strings, then should each value should directly
        correspond to the channel names. If a string is inputted and there are multiple
        channels, then it is assumed that the detector name is the same for each channel.
    relcal : ndarray, optional
        An array with the amplitude scalings between channels used when making the total
        If channels is supplied, relcal indices correspond to that list
        Default is all 1 (no relative scaling).
    convtoamps : float, optional
        The factor that the traces should be multiplied by to convert ADC bins to Amperes.
    fs : float, optional
        The sample rate in Hz of the data.
    filetype : str, optional
        The string that corresponds to the file type that will be opened. Supports two
        types: "mid.gz" and "npz". "mid.gz" is the default.
    lgcsavefile : bool, optional
        A boolean flag for whether or not to save the fake data to a file.
    savefilepath : str, optional
        The string that corresponds to the file path that will be saved.

    Returns
    -------
    None

    """

    seriesnumber = list(set(rq.seriesnumber[cut]))[0]

    ntraces = np.sum(cut)
    t, traces, _ = io.getrandevents(
        basepath,
        rq.eventnumber,
        rq.seriesnumber,
        cut=cut,
        channels=channels,
        det=det,
        convtoamps=convtoamps,
        fs=fs,
        ntraces=ntraces,
        filetype=filetype,
    )

    nchan = traces.shape[1]
    nbins = traces.shape[-1]
    t = np.arange(nbins) / fs

    if relcal is None:
        relcal = np.ones(nchan)
    elif nchan != len(relcal):
        raise ValueError('relcal must have length equal to number of channels')

    tracessum = np.sum(traces, axis=1)
    fakepulses = np.zeros(traces.shape)
    newtrace = np.zeros(tracessum.shape[-1])

    for ii in range(ntraces):
        newtrace[:] = tracessum[ii]

        if taurises is not None and taufalls is not None:
            for tr, tf, amp, td in zip(taurises, taufalls, amplitudes, tdelay):
                newtrace += amp[ii] * rp.make_ideal_template(
                    t, tr[ii], tf[ii], offset=td[ii] * fs)
        else:
            for temp, amp, td in zip(templates, amplitudes, tdelay):
                newtrace += amp[ii] * rp.shift(temp, td[ii] * fs)

        # multiply by reciprocal of the relative calibration such that when the processing script
        # creates the total channel pulse, it will be equal to newtrace
        for jj in range(nchan):
            if relcal[jj] != 0:
                fakepulses[ii, jj] = newtrace / (relcal[jj] * nchan)

    if lgcsavefile:
        if filetype == 'npz':
            savefilename = f"{seriesnumber:010}"
            savefilename = savefilename[:6] + '_' + savefilename[6:]
            savefilename = savefilename + "_fake_pulses"

            truthamps = np.stack(amplitudes, axis=1)
            truthtdelay = np.stack(tdelay, axis=1)
            trigtypes = np.zeros((ntraces, 3), dtype=bool)

            io.saveevents_npz(
                traces=fakepulses,
                trigtypes=trigtypes,
                truthamps=truthamps,
                truthtdelay=truthtdelay,
                savepath=savefilepath,
                savename=savefilename,
                dumpnum=dumpnum,
            )

        elif filetype == "mid.gz":
            savefilename = f"{seriesnumber:012}"
            savefilename = savefilename[:8] + '_' + savefilename[8:]

            if np.issubdtype(type(seriesnumber), np.integer):
                snum_str = f"{seriesnumber:012}"
                snum_str = snum_str[:8] + '_' + snum_str[8:]
            else:
                snum_str = seriesnumber

            full_settings_dict = getDetectorSettings(f"{basepath}{snum_str}",
                                                     "")

            settings_dict = {d: full_settings_dict[d] for d in det}

            for ch, d in zip(channels, det):
                settings_dict[d]["detectorType"] = 710
                settings_dict[d]["phononTraceLength"] = int(
                    settings_dict[d][ch]["binsPerTrace"])
                settings_dict[d]["phononPreTriggerLength"] = settings_dict[d][
                    "phononTraceLength"] // 2
                settings_dict[d]["phononSampleRate"] = int(
                    1 / settings_dict[d][ch]["timePerBin"])

            events_list = _create_events_list(
                tdelay[0],
                amplitudes[0],
                fakepulses,
                channels,
                det,
                convtoamps,
                seriesnumber,
                dumpnum,
            )

            io.saveevents_midgz(
                events=events_list,
                settings=settings_dict,
                savepath=savefilepath,
                savename=savefilename,
                dumpnum=dumpnum,
            )
        else:
            raise ValueError('Inputted filetype is not supported.')
예제 #3
0
def acquire_randoms(filelist,
                    n,
                    l,
                    datashape=None,
                    iotype="stanford",
                    savepath=None,
                    savename=None,
                    dumpnum=1,
                    maxevts=1000,
                    convtoamps=1 / 1024):
    """
    Function for acquiring random traces from a list of files and saving the results
    to a .npz file for later processing.
    
    Parameters
    ----------
    filelist : list of strings
        List of files to be opened to take random sections from (should be full paths)
    n : int
        Number of sections to choose
    l : int
        Length in bins of sections
    datashape : tuple, NoneType, optional
        The shape of the data in each file. If inputted, this should be a tuple that is 
        (# of traces in a dataset, # of bins in each trace). If left as None, then the first file 
        in filelist is opened, and the shape of the data in it is used.
    iotype : string, optional
        Type of file to open, uses a different IO function. Default is "stanford".
            "stanford" : Use qetpy.io.loadstanfordfile to open the files
    savepath : NoneType, str, optional
        Path to save the events to, if saveevents is True. If this is left as None, then they will
        be saved in the current working directory.
    savename : NoneType, str, optional
        Filename to save the events as. It is recommended that this follows CDMS format, which is 
        "[code][lasttwodigitsofyear][month][day]_[24hourclocktime]". If this is left as None, then 
        a dummy filename is used based on the inputted filelist.
    dumpnum : int, optional
        The dump number that the file should start saving from and the event number should be 
        determined by when saving. Default is 1.
    maxevts : int, optional
        The maximum number of events that should be stored in each dump when saving. Default
        is 1000.
    convtoamps : float, optional
        Correction factor to convert the data to Amps. The traces are multiplied by this
        factor, as is the TTL channel (if it exists). Default is 1/1024.
                
        
    """

    if savepath is None or not savepath:
        savepath = "./"

    if not savepath.endswith("/"):
        savepath += "/"

    if savename is None:
        now = datetime.datetime.now()
        savename = now.strftime("%Y%m%d_%H%M")

    if isinstance(filelist, str):
        filelist = [filelist]

    if datashape is None:
        # get the shape of data from the first dataset, we assume the shape is the same for all files
        if iotype == "stanford":
            traces = io.loadstanfordfile(filelist[0])[0]
            datashape = (traces.shape[0], traces.shape[-1])
        else:
            raise ValueError("Unrecognized iotype inputted.")

    nmax = int(datashape[-1] / l)
    choicelist = list(range(len(filelist))) * nmax * datashape[0]
    np.random.shuffle(choicelist)
    rows = np.array(choicelist[:n])
    counts = Counter(rows)

    evttimes_list = []
    res_list = []

    evt_counter = 0

    for key in counts.keys():

        if iotype == "stanford":
            traces, t, fs, _ = io.loadstanfordfile(filelist[key],
                                                   convtoamps=convtoamps)
        else:
            raise ValueError("Unrecognized iotype inputted.")

        et, r = rand_sections(traces, counts[key], l, t=t, fs=fs)

        evt_counter += len(et)

        evttimes_list.append(et)
        res_list.append(r)

        if evt_counter >= maxevts:

            evttimes = np.concatenate(evttimes_list)
            res = np.vstack(res_list)
            del evttimes_list
            del res_list
            trigtypes = np.zeros((len(evttimes), 3), dtype=bool)
            trigtypes[:, 0] = True

            for ii in range(len(evttimes) // maxevts):

                io.saveevents_npz(randomstimes=evttimes[:maxevts],
                                  traces=res[:maxevts],
                                  trigtypes=trigtypes[:maxevts],
                                  savepath=savepath,
                                  savename=savename,
                                  dumpnum=dumpnum)
                dumpnum += 1

                evttimes = evttimes[maxevts:]
                res = res[maxevts:]
                trigtypes = trigtypes[maxevts:]

            if len(evttimes) / maxevts > 1:
                evttimes_list = [evttimes]
                res_list = [res]
                evt_counter = len(evttimes)
            else:
                evttimes_list = []
                res_list = []
                evt_counter = 0

    # clean up the remaining events
    if evt_counter > 0:

        evttimes = np.concatenate(evttimes_list)
        res = np.vstack(res_list)

        del evttimes_list
        del res_list

        trigtypes = np.zeros((len(evttimes), 3), dtype=bool)
        trigtypes[:, 0] = True

        for ii in range(np.ceil(len(evttimes) / maxevts).astype(int)):

            io.saveevents_npz(randomstimes=evttimes[:maxevts],
                              traces=res[:maxevts],
                              trigtypes=trigtypes[:maxevts],
                              savepath=savepath,
                              savename=savename,
                              dumpnum=dumpnum)
            dumpnum += 1

            if ii + 1 != np.ceil(len(evttimes) / maxevts).astype(int):
                evttimes = evttimes[maxevts:]
                res = res[maxevts:]
                trigtypes = trigtypes[maxevts:]