Esempio n. 1
0
def GetWaveDataR(configFileName,
                 directoryName,
                 fileNum=1,
                 getZeroCrossingIntegral=True):
    startTime = time.time()
    print("Running GetWaveData!")
    print("Starting at " + time.strftime('%H:%M:%S'))
    config = configparser.ConfigParser()
    config.read(configFileName)

    # Setup data info
    # Directories

    data_directory = directoryName  # New

    data_file_name = config['Directories']['data_file_name']
    #pywaves_directory = config['Directories']['pywaves_directory']

    # Digitizer
    dataFormatStr = config['Digitizer']['dataFormat']
    nSamples = int(config['Digitizer']['samples_per_waveform'])
    ns_per_sample = int(config['Digitizer']['ns_per_sample'])
    number_of_bits = int(config['Digitizer']['number_of_bits'])
    dynamic_range_volts = float(config['Digitizer']['dynamic_range_volts'])
    polarity0 = int(
        config['Digitizer']['polarity0'])  # Polarity of first several channels
    p0ch = int(config['Digitizer']
               ['p0ch'])  # Number of channels to apply first polarity to
    polarity1 = int(
        config['Digitizer']['polarity1'])  # Polarity of remaining channels
    baselineOffset = int(config['Digitizer']['baseline_offset'])
    nBaselineSamples = int(config['Digitizer']['baseline_samples'])
    nCh = int(config['Digitizer']['number_of_channels'])

    # nWavesPerLoad = int(config['Data Management']['waves_per_load'])
    nWavesPerLoad = 10000  # Chosen pretty arbitrarily
    # nWaves = int(config['Data Management']['waves_per_folder']) # per folder
    nWaves = 1000000  # Large number
    # Let's just do all of the folders!
    startFolder = int(config['Data Management']['start_folder'])
    nFolders = fileNum
    # nFolders = int(config['Data Management']['number_of_folders'])

    unevenFactor = int(config['Data Management']['uneven_factor'])
    cfdFraction = float(config['Pulse Processing']['cfd_fraction'])
    integralEnd = int(config['Pulse Processing']['integral_end'])
    totalIntegralStart = int(
        config['Pulse Processing']['total_integral_start'])
    tailIntegralStart = int(config['Pulse Processing']['tail_integral_start'])
    applyCRRC4 = bool(int(config['Pulse Processing']['apply_crrc4']))
    CRRC4Tau = float(config['Pulse Processing']['crrc4_shaping_time'])

    # Load pywaves
    # sys.path.extend([pywaves_directory])
    from dataloader import DataLoader
    from waveform import Waveform

    # Pre-calc
    if dataFormatStr == 'DPP_MIXED':
        dataFormat = DataLoader.DAFCA_DPP_MIXED
    elif dataFormatStr == 'STANDARD':
        dataFormat = DataLoader.DAFCA_STD
    if platform.system() is 'Windows':
        directory_separator = '\\'
    else:
        directory_separator = '/'

    # Initialize data arrays
    dataFile1 = data_directory + directory_separator + str(
        1) + directory_separator + data_file_name
    datloader1 = DataLoader(dataFile1, dataFormat, nSamples)
    nWavesIn1 = datloader1.GetNumberOfWavesInFile()
    # print(str(nWavesIn1))

    nLoads = int(nWavesIn1 / nWavesPerLoad)
    if nLoads < 1:
        nLoads = 1
    chBufferSize = int(nFolders * nWavesIn1 * unevenFactor / nCh)
    VperLSB = dynamic_range_volts / (2**number_of_bits)
    fileTimeGap = 2**43  # Note: no more than 3 hours per measurement!

    # Setup channel queues
    ph = np.zeros((nCh, chBufferSize))
    amp = np.zeros((nCh, chBufferSize))
    tailInt = np.zeros((nCh, chBufferSize))
    totalInt = np.zeros((nCh, chBufferSize))
    rms = np.zeros((nCh, chBufferSize))
    ttt = np.zeros((nCh, chBufferSize), dtype=np.uint32)
    extras = np.zeros((nCh, chBufferSize), dtype=np.uint32)
    fullTime = np.zeros((nCh, chBufferSize), dtype=np.uint64)
    cfd = np.zeros((nCh, chBufferSize))
    chCount = np.zeros(nCh, dtype=np.uint32)
    flags = np.zeros((nCh, chBufferSize), dtype=np.uint32)

    # Setup data loader
    waveform = Waveform(np.zeros(nSamples), polarity0, baselineOffset,
                        nBaselineSamples)
    print('polarity0 =' + str(polarity0))
    print('p0ch = ' + str(p0ch))
    print('polarity1 =' + str(polarity1))

    # Queue up waves
    for f in range(startFolder, startFolder + nFolders):
        print('Folder {}:'.format(f))
        fullDFileName = data_directory + directory_separator + str(
            f) + directory_separator + data_file_name
        datloader = DataLoader(fullDFileName, dataFormat, nSamples)
        nWavesInFile = datloader.GetNumberOfWavesInFile()
        nWaves = nWavesInFile + 1
        if (nWavesInFile < nWaves):
            print('Warning: requested more waves than exists in file!')
            loadsInFile = int(np.ceil(nWavesInFile / nWavesPerLoad))
            print('Loading all {} waves instead...'.format(nWavesInFile))
            lastLoad = nWavesInFile - (loadsInFile - 1) * nWavesPerLoad
        else:
            loadsInFile = nLoads
            lastLoad = nWavesPerLoad
        if nWavesInFile % 2 == 0 or nWavesInFile % 2 == 1 or int(nCh) == 2:
            for load in range(loadsInFile):
                if (load == loadsInFile - 1):
                    wavesThisLoad = lastLoad
                else:
                    wavesThisLoad = nWavesPerLoad
                waves = datloader.LoadWaves(wavesThisLoad)
                for w in range(wavesThisLoad):
                    ch = waves[w]['Channel']
                    waveform.SetSamples(waves[w]['Samples'])
                    if (ch >= p0ch):
                        waveform.Polarize(polarity1)
                    else:
                        waveform.Polarize(polarity0)
                    #print(str( waveform.polarity))
                    if applyCRRC4:
                        waveform.ApplyCRRC4(ns_per_sample, CRRC4Tau)
                    if getZeroCrossingIntegral:
                        ph[ch][
                            chCount[ch]] = waveform.GetIntegralToZeroCrossing(
                            ) * VperLSB * ns_per_sample
                    amp[ch][chCount[ch]] = waveform.GetMax()
                    tailInt[ch][chCount[ch]] = waveform.GetIntegralFromPeak(
                        tailIntegralStart,
                        integralEnd) * VperLSB * ns_per_sample
                    totalInt[ch][chCount[ch]] = waveform.GetIntegralFromPeak(
                        totalIntegralStart,
                        integralEnd) * VperLSB * ns_per_sample
                    cfd[ch][chCount[ch]] = waveform.GetCFDTime(
                        cfdFraction) * ns_per_sample
                    ttt[ch][chCount[ch]] = waves[w]['TimeTag']
                    rms[ch][chCount[ch]] = waveform.GetRMSbls(nBaselineSamples)
                    if dataFormatStr == 'DPP_MIXED':
                        extras[ch][chCount[ch]] = waves[w]['Extras']
                        #                    fullTime[ch][chCount[ch]] = ((waves[w]['TimeTag'] +
                        #                                                ((waves[w]['Extras'] & 0xFFFF0000)
                        #                                                << 15)))*ns_per_sample
                        fullTime[ch][chCount[ch]] = (
                            (waves[w]['TimeTag'] +
                             ((waves[w]['Extras'] & 0xFFFF0000) << 15)) +
                            fileTimeGap * f) * ns_per_sample
                    chCount[ch] += 1
    endTime = time.time()
    runTime = endTime - startTime
    print("GetWaveDataR took {} s".format(runTime))
    return chCount, ph, amp, tailInt, totalInt, cfd, ttt, extras, fullTime, flags, rms
Esempio n. 2
0
def GetWaveData(configFileName,
                getZeroCrossingIntegral=True,
                getWaves=True,
                loud=False,
                getTail=False,
                getTot=False,
                getPH=False,
                getAmp=False,
                getRMS=False,
                getExtras=False,
                getFullTime=False,
                getCFD=False,
                getflags=False):

    # --------------------------------------------------------------------------------------------------------------------- #
    #    Configuration
    # --------------------------------------------------------------------------------------------------------------------- #

    config = configparser.ConfigParser()
    config.read(configFileName)

    # Setup data info
    # Directories
    data_directory = config['Directories']['data_directory']
    data_file_name = config['Directories']['data_file_name']
    goodInd = False
    if 'goodind_file_name' in config['Directories']:
        goodInd = True
        goodind_file_name = config['Directories']['goodind_file_name']
    pywaves_directory = config['Directories']['pywaves_directory']

    # Load pywaves
    sys.path.extend([pywaves_directory])
    from dataloader import DataLoader
    from waveform import Waveform

    # Digitizer
    global dataFormatStr
    global nSamples
    global ns_per_sample
    global number_of_bits
    global dynamic_range_volts
    global polarity
    global baselineOffset
    global nBaselineSamples
    global nCh
    global nWavesPerLoad
    global nWaves
    global startFolder
    global nFolders
    global unevenFactor
    global cfdFraction
    global integralEnd
    global totalIntegralStart
    global tailIntegralStart
    global applyCRRC4
    global CRRC4Tau

    dataFormatStr = config['Digitizer']['dataFormat']
    nSamples = int(config['Digitizer']['samples_per_waveform'])
    ns_per_sample = int(config['Digitizer']['ns_per_sample'])
    number_of_bits = int(config['Digitizer']['number_of_bits'])
    dynamic_range_volts = float(config['Digitizer']['dynamic_range_volts'])
    polarity = int(config['Digitizer']['polarity'])
    baselineOffset = int(config['Digitizer']['baseline_offset'])
    nBaselineSamples = int(config['Digitizer']['baseline_samples'])
    nCh = int(config['Digitizer']['number_of_channels'])
    nWavesPerLoad = int(config['Data Management']['waves_per_load'])
    nWaves = int(config['Data Management']['waves_per_folder'])  # per folder
    startFolder = int(config['Data Management']['start_folder'])
    nFolders = int(config['Data Management']['number_of_folders'])
    unevenFactor = int(config['Data Management']['uneven_factor'])
    cfdFraction = float(config['Pulse Processing']['cfd_fraction'])
    integralEnd = int(config['Pulse Processing']['integral_end'])
    totalIntegralStart = int(
        config['Pulse Processing']['total_integral_start'])
    tailIntegralStart = int(config['Pulse Processing']['tail_integral_start'])
    applyCRRC4 = bool(int(config['Pulse Processing']['apply_crrc4']))
    CRRC4Tau = float(config['Pulse Processing']['crrc4_shaping_time'])

    # Pre-calc
    if dataFormatStr == 'DPP_MIXED':
        dataFormat = DataLoader.DAFCA_DPP_MIXED
    elif dataFormatStr == 'STANDARD':
        dataFormat = DataLoader.DAFCA_STD
    if platform.system() is 'Windows':
        directory_separator = '\\'
    else:
        directory_separator = '/'
    nLoads = int(nWaves / nWavesPerLoad)
    chBufferSize = int(nFolders * nWaves * unevenFactor / nCh)
    VperLSB = dynamic_range_volts / (2**number_of_bits)
    fileTimeGap = 2**43  # Note: no more than 3 hours per measurement!

    # --------------------------------------------------------------------------------------------------------------------- #
    #    Data structure setup
    # --------------------------------------------------------------------------------------------------------------------- #

    dataGetter = {}
    dataStorage = {}

    if getTail == True:
        dataGetter['tail'] = getWaveTail
        dataStorage['tail'] = np.zeros((nCh, chBufferSize))
    if getTot == True:
        dataGetter['total'] = getWaveTot
        dataStorage['total'] = np.zeros((nCh, chBufferSize))
    if getPH == True:
        dataGetter['ph'] = getWavePH
        dataStorage['ph'] = np.zeros((nCh, chBufferSize))
    if getCFD == True:
        dataGetter['cfd'] = getWaveCFD
        dataStorage['cfd'] = np.zeros((nCh, chBufferSize))
    if getRMS == True:
        dataGetter['rms'] = getWaveRMS
        dataStorage['rms'] = np.zeros((nCh, chBufferSize))
    if getAmp == True:
        dataGetter['amp'] = getWaveAmp
        dataSotage['amp'] = np.zeros((nCh, chBufferSize))

    if getExtras == True and dataFormatStr == 'DPP_MIXED':
        dataSotage['extra'] = np.zeros((nCh, chBufferSize), dtype=np.uint32)
    if getFullTime == True and dataFormatStr == 'DPP_MIXED':
        dataSotage['fulltime'] = np.zeros((nCh, chBufferSize), dtype=np.uint64)

    # Setup mandatory channel queues
    ttt = np.zeros((nCh, chBufferSize), dtype=np.uint32)
    chCount = np.zeros(nCh, dtype=np.uint32)
    flags = np.zeros((nCh, chBufferSize), dtype=np.uint32)

    # --------------------------------------------------------------------------------------------------------------------- #
    #    Data aquisition
    # --------------------------------------------------------------------------------------------------------------------- #

    startTime = time.time()
    print("Running GetWaveData!")
    print("Starting at " + time.strftime('%H:%M:%S'))

    # Setup data loader
    waveform = Waveform(np.zeros(nSamples), polarity, baselineOffset,
                        nBaselineSamples)

    pulses = []
    # Queue up waves
    for f in range(startFolder, startFolder + nFolders):
        print('\n Folder {}:'.format(f))
        fullDFileName = data_directory + directory_separator + str(
            f) + directory_separator + data_file_name
        print(fullDFileName)

        datloader = DataLoader(fullDFileName, dataFormat, nSamples)
        nWavesInFile = datloader.GetNumberOfWavesInFile()

        if (nWavesInFile < nWaves):
            print('Warning: requested more waves than exists in file!')
            loadsInFile = int(np.ceil(nWavesInFile / nWavesPerLoad))
            print('Loading all {} waves instead...'.format(nWavesInFile))
            lastLoad = nWavesInFile - (loadsInFile - 1) * nWavesPerLoad

        else:
            loadsInFile = nLoads
            lastLoad = nWavesPerLoad

        if goodInd == True:
            goodIndFileName = data_directory + directory_separator + str(
                f) + directory_separator + goodind_file_name
            goodIndices = []
            with open(goodIndFileName, "r") as goodfi:
                good_lines = goodfi.readlines()
                for line in good_lines:
                    goodIndices.append(int(line) - 1)
            goodIndices = np.array(goodIndices)
        else:
            goodIndices = np.arange(0, nWavesInFile - 1)

        waveNum = 0
        printProgressBar(0,
                         loadsInFile,
                         prefix='Progress: ',
                         suffix='Complete')
        for load in range(loadsInFile):
            if (load == loadsInFile - 1):
                wavesThisLoad = lastLoad
            else:
                wavesThisLoad = nWavesPerLoad
            waves = datloader.LoadWaves(wavesThisLoad)
            for w in range(0, wavesThisLoad):
                if waveNum == goodIndices[0]:
                    goodIndices = goodIndices[1:]
                    ch = waves[w]['Channel']
                    chCount[ch] += 1

                    # set up waveform structure
                    waveform = Waveform(waves[w]['Samples'],
                                        polarity,
                                        baselineOffset,
                                        nBaselineSamples,
                                        ch=waves[w]['Channel'],
                                        time=waves[w]['TimeTag'])
                    waveform.BaselineSubtract()

                    # CCR4
                    if applyCRRC4:
                        waveform.ApplyCRRC4(ns_per_sample, CRRC4Tau)

                    # add timing data to mandatory channel structure
                    ttt[ch][chCount[ch]] = waves[w]['TimeTag']

                    # populate data structure for optional
                    for key, value in dataGetter.items():
                        dataStorage[key][ch][chCount[ch]] = getGetter[key](
                            waveform)

                        ttt[ch][chCount[ch]] = waves[w]['TimeTag']
                    # get the whole wave
                    if getWaves == True:
                        pulses.append(waveform)

                waveNum += 1  # increment the wave counter in the current load
            # end iteration over waves in load - end load

            # update progress bar following new load
            printProgressBar(load + 1,
                             loadsInFile,
                             prefix='Progress: ',
                             suffix='Complete')

    endTime = time.time()
    runTime = endTime - startTime
    print("\nGetWaveData took {} s".format(runTime))
    if getWaves == False:
        return chCount, ttt, dataStorage
    else:
        return chCount, ttt, dataStorage, pulses
Esempio n. 3
0
def Analyzing_Waves():

    print("\n")
    print("Data file to be analyzed: " + str(Data_File))
    print("\n")

    files = os.listdir(Path_to_Data)

    #if not os.mkdir(Output_Data_Path):
    #	os.mkdir(Output_Data_Path)

    if not os.path.exists(Output_Data_Path):
        os.makedirs(Output_Data_Path)

    for f in files:

        Data = DataLoader(Path_to_Data + str(f) + "/dataFile0.dat",
                          DataLoader.DAFCA_DPP_MIXED, Num_Samples)

        print("Reading in Folder: " + str(f))
        print("Number of waves: " + str(Data.GetNumberOfWavesInFile()))
        print("\n")

        Number_of_Waves = Data.GetNumberOfWavesInFile()
        Waves = Data.LoadWaves(Number_of_Waves)

        ##############################################
        ############### Data Structure ###############
        ##############################################
        ### ('Channel',(np.int16,1))
        ### ('PH',(np.float64,1))
        ### ('PI',(np.float64,1))
        ### ('DCFD',(np.float64,1))
        ###	('Timetag',(np.int32,1))
        ###	('Extras',(np.int32,1))
        ### ('Tail',(np.float64,1))
        ###	('Total',(np.float64,1))
        ##############################################
        ##############################################

        Data_Out = np.zeros((len(Waves), 9))

        for wave in np.arange(0, len(Waves), 1):

            #print(Waves[wave]['EventSize'])
            #print(Waves[wave]['Format'])
            #print(Waves[wave]['Channel'])
            #print(Waves[wave]['Baseline'])
            #print(Waves[wave]['ShortGate'])
            #print(Waves[wave]['LongGate'])
            #print(Waves[wave]['TimeTag'])
            #print(Waves[wave]['Extras'])
            #print(Waves[wave]['Samples'])
            #print("\n")

            Data_Out[wave][0] = Waves[wave]['Channel']

            Channel_Val = int(Waves[wave]['Channel'])

            Subtracted_Wave = BaselineSubtract(Waves[wave]['Samples'],
                                               nBaselineSamples)

            if Waves[wave]['Channel'] in Negative_Waves:
                #x = np.arange(0,Num_Samples,1)
                #plt.plot(x, Subtracted_Wave)
                #plt.show()
                #plt.close()

                Subtracted_Wave = Subtracted_Wave * (-1.0)

                #plt.plot(x, Subtracted_Wave)
                #plt.show()
                #plt.close()

                #print(Channel_Val)
                #print(tail_integral_start[Channel_Val])

            Max_index = np.argmax(Subtracted_Wave)
            #print(Max_index)

            #x = np.arange(0,Num_Samples,1)
            #plt.plot(x, Waves[wave]['Samples'])
            #plt.scatter(x[Max_index+tail_integral_start[Channel_Val]:Max_index+integral_end[Channel_Val]], Subtracted_Wave[Max_index+tail_integral_start[Channel_Val]:Max_index+integral_end[Channel_Val]])
            #plt.scatter(x[Max_index+total_integral_start[Channel_Val]:Max_index+integral_end[Channel_Val]], Subtracted_Wave[Max_index+total_integral_start[Channel_Val]:Max_index+integral_end[Channel_Val]])
            #plt.show()
            #plt.close()

            ph = np.max(Subtracted_Wave) * VperLSB
            PI = np.sum(Subtracted_Wave) * VperLSB * ns_per_sample

            Data_Out[wave][1] = ph
            Data_Out[wave][2] = PI

            DCFD = CFD(Subtracted_Wave, F)

            Data_Out[wave][3] = DCFD
            Data_Out[wave][4] = Waves[wave]['TimeTag']
            Data_Out[wave][5] = Waves[wave]['Extras']

            Tail = np.sum(
                Subtracted_Wave[Max_index +
                                tail_integral_start[Channel_Val]:Max_index +
                                integral_end[Channel_Val]])
            Total = np.sum(
                Subtracted_Wave[Max_index +
                                total_integral_start[Channel_Val]:Max_index +
                                integral_end[Channel_Val]])

            Data_Out[wave][6] = Tail
            Data_Out[wave][7] = Total

        Writing_Data(Data_Out, f)
def Using_DataLoader():
    '''
	##############################################

	Step #2: Three variables are required to run DataLoader.
	Variable #1, Data_File_Path: A path and data file must be specified.
	Variable #2, dataType: CAEN digitizers will output data in one of three 
	formats: DAFCA_STD, DAFCA_DPP_MIXED, or DAFCA_DPP_LIST. This defines the 
	data structure for how data is pulled in. We will go through DAFCA_DPP_MIXED
	thoroughly. 
	Variable #3, Num_Samples: This is the number of samples in a waveform, not 
	the number of waves

	##############################################
	'''

    ##############################################

    Data_File_Path = "C:/Users/Giha/Documents/N3Glass/X1/1/dataFile0.dat"
    dataType = DataLoader.DAFCA_DPP_MIXED
    Num_Samples = 500

    ##############################################

    Data = DataLoader(Data_File_Path, dataType, Num_Samples)

    print("DataLoader has two useful functions to new users.")
    print("\n")
    print(
        "The first useful function will tell you how many waves are in the specified file."
    )
    print("\n")
    time.sleep(3)

    Number_of_data_structures = Data.GetNumberOfWavesInFile()

    print("In : " + str(Data_File_Path) + " , there are " +
          str(Number_of_data_structures) +
          " pulses, or more specifically, that many data structures.")
    print("\n")
    time.sleep(1)
    print(
        "The second useful function will load in a specified number of waves or data structures."
    )
    print("\n")
    time.sleep(1)
    var = input(
        "Lets read in one wave and break down what we are reading in. Sound good? (Y/N): "
    )
    if var == "Y":
        Waves = Data.LoadWaves(1)
        print("\n")
        time.sleep(1)
        print("This one wave has the following structure:")
        print("\n")
        print('EventSize is the event size in number of bytes: ' +
              str(Waves['EventSize'][0]))
        print('Format is referring to the CAEN datatype: ' +
              str(Waves['Format'][0]))
        print('Channel is referring to the input channel on the digitizer: ' +
              str(Waves['Channel'][0]))
        print('Baseline is the baseline of the pulse: ' +
              str(Waves['Baseline'][0]))
        print('ShortGate is the tail integral of the pulse: ' +
              str(Waves['ShortGate'][0]))
        print('LongGate is the total integral of the pulse: ' +
              str(Waves['LongGate'][0]))
        print(
            'TimeTag is a course absolute time for when a pulse begins (ns): '
            + str(Waves['TimeTag'][0]))
        print(
            'Extras can be thought of as a finer time that can be combined with TimeTag: '
            + str(Waves['Extras'][0]))
        print('Samples are the actual wave samples: ' +
              str(Waves['Samples'][0]))

        print("\n")
        time.sleep(1)

        print(
            "Baseline, ShortGate, and LongGate have generally not been used because they do not necessarily accuratley represent what they claim to."
        )
        print(
            "For more infomration (especially when using Extras), please read the UM2580 DPP PSD User Manual found on CAEN's website."
        )
        print("\n")
        time.sleep(1)
        print(
            "Now let's plot this pulse. When you are happy with looking at the pulse, close the figure."
        )

        x = np.arange(0, Num_Samples * 2, 2)
        y = Waves['Samples'][0]
        plt.plot(x, y)
        plt.xlabel("Time (ns)")
        plt.xlabel("Digitizer Units")
        plt.show()
        plt.close()

        print("\n")
        time.sleep(1)
        print(
            "From this pulse, we can attain useful information, but first we must subtract the baseline."
        )
        print("\n")
        print(
            "In DAFCA, the user can specify how much data of the pulse they want before the rising edge. This way a sufficient amount of data can be acquired to determine the baseline."
        )
        print(
            "Generally, the baseline is determined by averaging the first 50 samples of the pulse."
        )
        time.sleep(1)
        Baseline = np.average(Waves['Samples'][0][0:50])
        print("\n")
        print("In this case, the baseline of the pulse is: " + str(Baseline))
        print("\n")
        print("We can now subtract this baseline and plot the pulse.")
        print("\n")

        Baseline_Subtracted_Wave = Waves['Samples'][0] - Baseline

        x = np.arange(0, Num_Samples * 2, 2)
        y = Baseline_Subtracted_Wave
        plt.plot(x, y)
        plt.xlabel("Time (ns)")
        plt.xlabel("Digitizer Units")
        plt.show()
        plt.close()

        print("We can now attain some useful information about the pulse:")
        print("\n")

        Pulse_Height = np.max(Baseline_Subtracted_Wave)
        Max_Index = np.argmax(Baseline_Subtracted_Wave)
        negativeSamples = np.nonzero(
            Baseline_Subtracted_Wave[Max_Index:] < 0)[0]
        Pulse_Integral = np.sum(
            Baseline_Subtracted_Wave[:Max_Index + negativeSamples[0]]) * 2

        dynamic_range_volts = 0.5
        number_of_bits = 15

        VperLSB = dynamic_range_volts / (2**number_of_bits)

        F = 0.2

        Start_Time = CFD(Baseline_Subtracted_Wave, F)

        print("Pulse Height (Digitizer Units): " + str(Pulse_Height))
        print("Pulse Integral (Digitizer Units-ns): " + str(Pulse_Integral))
        print("Start Time (ns): " + str(Start_Time))
        print("\n")
        print(
            "To convert from Digitizer Units to Votlage, it is necessary to multiply by the dynamic range of the digitizer and divide by 2^(number of bits). In this case the conversion is 0.5/2^14. This yields:"
        )
        print("\n")

        Pulse_Height = np.max(Baseline_Subtracted_Wave) * VperLSB
        Pulse_Integral = np.sum(
            Baseline_Subtracted_Wave[:Max_Index +
                                     negativeSamples[0]]) * 2 * VperLSB

        print("Pulse Height (mV): " + str(Pulse_Height))
        print("Pulse Integral (mV-ns): " + str(Pulse_Integral))
        print("\n")
        print("The next code, GetWaveData, does these calculations for us.")
        print("\n")

        x = np.arange(0, Num_Samples * 2, 2)
        y = Baseline_Subtracted_Wave
        plt.plot(x, y)
        plt.xlabel("Time (ns)")
        plt.xlabel("Digitizer Units")
        plt.show()
        plt.close()

    else:
        print("Fine.")