def calculateCenterOfSensorPerBatch(pulse_amplitude, tracking):

    # Calculate position for largest batches
    if md.getBatchNumber() not in [101, 207, 306, 401, 507, 601, 707]:
        return 0

    global canvas_center

    canvas_center = ROOT.TCanvas("c1", "c1")

    print "\nCalculating CENTER POSITIONS for batch", md.getBatchNumber(), "\n"

    position_temp = np.zeros(1, dtype=dm.getDTYPETrackingPosition())

    for chan in pulse_amplitude.dtype.names:
        md.setChannelName(chan)
        print md.getSensor()

        position_temp[chan][0] = getCenterOfSensor(pulse_amplitude[chan],
                                                   np.copy(tracking))

    dm.exportImportROOTData("tracking", "position", position_temp)

    print "\nDONE producing CENTER POSITIONS for batch", md.getBatchNumber(
    ), "\n"
def produceTimingDistributionPlots(time_difference, category):

    group = "timing"

    if category.find("system") != -1:

        # Comment this function if you want to omit producing plots for system of equations
        produceTimingDistributionPlotsSysEq(time_difference, category)
        return 0

    text = "\nSiPM-DUT TIME DIFFERENCE (PEAK) BATCH " + str(md.getBatchNumber()) + "\n"

    if category.find("cfd") != -1:
        text = text.replace("PEAK", "CFD")

    print text
    
    time_diff_TH1F = dict()

    for chan in time_difference.dtype.names:
        
        md.setChannelName(chan)

        # Omit sensors which are not analyzed (defined in main.py)
        if (md.getSensor() != md.sensor and md.sensor != "") or md.getSensor() == "SiPM-AFP":
            continue
        
        print md.getSensor(), "\n"

        th_name = "_" + str(md.getBatchNumber()) + "_" + md.chan_name
        time_diff_TH1F[chan] = ROOT.TH1F(category + th_name, category, xbins, -fill_range, fill_range)
     
        # Fill the objects
        for entry in range(0, len(time_difference[chan])):
            
            if time_difference[chan][entry] != 0:
                time_diff_TH1F[chan].Fill(time_difference[chan][entry])

        # Get fit function with width of the distributions
        # Check if the filled object have at a minimum of required entries
        
        if time_diff_TH1F[chan].GetEntries() < min_entries_per_run * len(md.getAllRunNumbers(md.getBatchNumber())):
            
            if category.find("cfd") != -1:
                type = "cfd reference"
            
            else:
                type = "peak reference"
                
            print "Omitting sensor", md.getSensor(), "for", type, "due to low statistics. \n"
            
            continue
            
        sigma_DUT, sigma_fit_error = t_calc.getSigmasFromFit(time_diff_TH1F[chan], window_range, percentage)

        exportTHPlot(time_diff_TH1F[chan], [sigma_DUT, sigma_fit_error], category)
def timingPlots():

    print "\nStart producing TIMING RESOLUTION plots, batches:", md.batchNumbers, "\n"

    global var_names
    
    for batchNumber in md.batchNumbers:

        runNumbers = md.getAllRunNumbers(batchNumber)
        
        # Create numpy arrays for linear time difference (one element per "channel")
        numpy_arrays = [np.empty(0, dtype = dm.getDTYPE(batchNumber)) for _ in range(2)]

        # Create numpy arrays for system of equations (three elements per "channel")
        numpy_arrays.append(np.empty(0, dtype = dm.getDTYPESysEq()))
        numpy_arrays.append(np.empty(0, dtype = dm.getDTYPESysEq()))

        var_names = ["normal_peak", "normal_cfd", "system_peak", "system_cfd"]
       
        for runNumber in runNumbers:
        
            md.defineRunInfo(md.getRowForRunNumber(runNumber))
            
            if not dm.checkIfROOTDataFileExists("timing", "normal_peak"):
                t_calc.createTimingFiles(batchNumber)
            
            # Skip runs which are not in synch
            if runNumber not in md.getRunsWithSensor() or runNumber in [3697, 3698, 3701]:
                continue
        
            for index in range(0, len(var_names)):
            
                # omit batch 60X for solving system of equations
                if var_names[index].find("system") != -1 and md.getBatchNumber()/100 == 6:
                    continue
                
                else:
                    numpy_arrays[index] = np.concatenate((numpy_arrays[index], dm.exportImportROOTData("timing", var_names[index])), axis = 0)

        if numpy_arrays[0].size != 0:
            
            for index in range(0, len(var_names)):
            
                # omit batch 60X for solving system of equations
                if var_names[index].find("system") != -1 and md.getBatchNumber()/100 == 6:
                    continue
                
                else:
                    produceTimingDistributionPlots(numpy_arrays[index], var_names[index])


    print "\nDone with producing TIMING RESOLUTION plots.\n"
示例#4
0
def exportImportROOTData(group, category, data=np.empty(0)):

    dataPath = getDataSourceFolder() + "/" + group + "/"

    # This line is for exporting data and adapting correct dtype for the numpy array
    if group != "timing" and group != "results" and category != "position" and data.size != 0:
        data = data.astype(getDTYPE())

    if group == "tracking":

        if category == "tracking":
            fileName = category + str(md.getTimeStamp())

        elif category == "efficiency":
            fileName = category + "_" + str(md.getBatchNumber(
            )) + "_" + md.getSensor() + "_" + md.chan_name

        # Position
        else:
            fileName = category + "_" + str(md.getBatchNumber() / 100)

        dataPath += category + "/" + fileName + ".root"

    elif group == "timing":

        category, subcategory = category.split("_")

        fileName = group + "_" + category + "_" + subcategory + "_" + str(
            md.getRunNumber())

        dataPath += category + "/" + subcategory + "/" + fileName + ".root"

    else:

        fileName = group + "_" + category + "_" + str(md.getRunNumber())

        dataPath += category + "/" + fileName + ".root"

    # read the file
    if data.size == 0:

        try:
            return rnm.root2array(dataPath)

        except IOError as e:

            print "\nFile", fileName + ".root", "not found!\n"
            return np.zeros(1)

    # export the file
    else:
        rnm.array2root(data, dataPath, mode="recreate")
示例#5
0
def getFileNameForHistogram(group, category, subcategory="", chan2=""):

    # pulse all types
    fileName = getPlotsSourceFolder() + "/" + md.getSensor(
    ) + "/" + group + "/" + category + "/" + group + "_" + category + "_" + str(
        md.getBatchNumber()) + "_" + md.chan_name
    ending = "_" + md.getSensor() + ".pdf"

    # timing resolution
    if subcategory != "":

        if md.checkIfSameOscAsSiPM():

            getOscText = "same_osc"

        else:
            getOscText = "diff_osc"

        # timing normal
        fileName = fileName.replace(category + "/",
                                    category + "/" + subcategory + "/", 1)
        ending = "_" + md.getSensor(
        ) + "_" + getOscText + "_" + subcategory + ".pdf"

        # sys eq
        if chan2 != "":
            ending = "_" + md.getSensor() + "_and_" + md.getSensor(
                chan2) + "_" + subcategory + ".pdf"

    # For array-pad tracking plots
    if group == "tracking" and t_calc.array_pad_export:
        ending = ending.replace(".pdf", "_array.pdf")

    return fileName + ending
示例#6
0
def getDTYPE(batchNumber=0):

    if batchNumber == 0:
        batchNumber = md.getBatchNumber()

    # Batch 60X have 3 channels
    if batchNumber / 100 == 6:

        dtype = np.dtype([('chan0', '<f8'), ('chan1', '<f8'),
                          ('chan2', '<f8')])

    # Batch 30X have 7 channels
    elif batchNumber / 100 == 3:

        dtype = np.dtype([('chan0', '<f8'), ('chan1', '<f8'), ('chan2', '<f8'),
                          ('chan3', '<f8'), ('chan4', '<f8'), ('chan5', '<f8'),
                          ('chan6', '<f8')])

    # Remaining batches have 8 channels
    else:

        dtype = np.dtype([('chan0', '<f8'), ('chan1', '<f8'), ('chan2', '<f8'),
                          ('chan3', '<f8'), ('chan4', '<f8'), ('chan5', '<f8'),
                          ('chan6', '<f8'), ('chan7', '<f8')])

    return dtype
def fillTHObjects(numpy_arrays, max_sample, TH2_pulse, TH2_timing, tracking,
                  th1_limits):

    [xbin, ybin, xbin_timing, ybin_timing, distance_x,
     distance_y] = [i for i in th1_limits]

    # Create time difference objects, with standard deviation as error in each bin
    th_name = "_" + str(md.getBatchNumber()) + "_" + md.chan_name
    time_difference_peak_TH2D = ROOT.TProfile2D(
        "timing_peak" + th_name + "temp", "timing_peak", xbin_timing,
        -distance_x, distance_x, ybin_timing, -distance_y, distance_y, "s")
    time_difference_cfd_TH2D = ROOT.TProfile2D("timing_cfd" + th_name + "temp",
                                               "timing_cfd", xbin_timing,
                                               -distance_x, distance_x,
                                               ybin_timing, -distance_y,
                                               distance_y, "s")

    # Remove large values
    stripNumpyArrays(numpy_arrays, max_sample, TH2_pulse, TH2_timing)
    TH2_objects_fill = [i for i in TH2_pulse]
    TH2_objects_fill.append(time_difference_peak_TH2D)
    TH2_objects_fill.append(time_difference_cfd_TH2D)

    # Fill all objects
    for event in range(0, len(tracking)):
        if (-distance_x < tracking['X'][event] < distance_x) and (
                -distance_y < tracking['Y'][event] < distance_y):
            for index in range(0, len(numpy_arrays)):
                if numpy_arrays[index][event] != 0:
                    TH2_objects_fill[index].Fill(tracking['X'][event],
                                                 tracking['Y'][event],
                                                 numpy_arrays[index][event])

    # Remove bins with few entries
    for i in range(1, xbin + 1):
        for j in range(1, ybin + 1):
            for index in range(0, len(TH2_pulse)):
                bin = TH2_pulse[index].GetBin(i, j)
                removeBin(bin, TH2_pulse[index])

    for index in range(0, len(TH2_pulse)):
        TH2_pulse[index].ResetStats()

    # Save the number of entries, to restore for the new TH1D object showing the timing resolution
    entries_timing_resolution = [
        time_difference_peak_TH2D.GetEntries(),
        time_difference_cfd_TH2D.GetEntries()
    ]

    # Fill timing resolution bins
    for i in range(1, xbin_timing + 1):
        for j in range(1, ybin_timing + 1):
            for index in range(0, len(TH2_timing)):
                bin = TH2_timing[index].GetBin(i, j)
                fillTimeResBin(bin, TH2_objects_fill[index + 3],
                               TH2_timing[index])

    del time_difference_peak_TH2D, time_difference_cfd_TH2D

    return entries_timing_resolution
示例#8
0
def produceTProfilePlots(numpy_arrays, max_sample, tracking, distance_x, distance_y):
    
    if md.checkIfArrayPad():
        
        distance_x *= 2
        distance_y *= 2
    
    # Adaptive bin number
    xbin = int(2*distance_x/bin_size)
    ybin = int(2*distance_y/bin_size)
    
    # Decreased number of bins for timing resolution plots
    xbin_timing = int(xbin/bin_timing_decrease)
    ybin_timing = int(ybin/bin_timing_decrease)

    th_name = "_"+str(md.getBatchNumber())+"_"+md.chan_name
    
    # Declare ROOT objects
    pulse_amplitude_TH2D   = ROOT.TProfile2D("pulse_amplitude"+th_name, "pulse_amplitude", xbin, -distance_x, distance_x, ybin, -distance_y, distance_y)
    gain_TH2D              = ROOT.TProfile2D("gain"+th_name,"gain", xbin, -distance_x, distance_x, ybin, -distance_y, distance_y)
    rise_time_TH2D         = ROOT.TProfile2D("rise_time"+th_name,"rise_time", xbin, -distance_x, distance_x, ybin, -distance_y, distance_y)
    
    timing_peak_TH2D       = ROOT.TH2D("timing_peak"+th_name, "timing_peak", xbin_timing, -distance_x, distance_x, ybin_timing, -distance_y, distance_y)
    timing_cfd_TH2D        = ROOT.TH2D("timing_cfd"+th_name, "timing_cfd", xbin_timing, -distance_x, distance_x, ybin_timing, -distance_y, distance_y)
    
    TH2_pulse = [pulse_amplitude_TH2D, gain_TH2D, rise_time_TH2D]
    TH2_timing = [timing_peak_TH2D, timing_cfd_TH2D]
    entries_timing_resolution = t_calc.fillTHObjects(numpy_arrays, max_sample, TH2_pulse, TH2_timing, tracking, [xbin, ybin, xbin_timing, ybin_timing, distance_x, distance_y])
  
    # Print pulse amplitude mean value 2D plot
    TH2D_objects = [pulse_amplitude_TH2D, gain_TH2D, rise_time_TH2D, timing_peak_TH2D, timing_cfd_TH2D, 0, 0]
    setPlotLimitsAndPrint(TH2D_objects, entries_timing_resolution)
示例#9
0
def produceEfficiencyPlot(pulse_amplitude, tracking, distance_x, distance_y):
    
    if md.checkIfArrayPad():
    
        distance_x *= 2
        distance_y *= 2

    # Define how many bins to use for the TH2-objects
    xbin = int(2*distance_x/bin_size)
    ybin = int(2*distance_y/bin_size)

    # Fill events for which the sensors records a hit
    LGAD_TH2D         = ROOT.TH2D("LGAD_particles", "LGAD particles",xbin,-distance_x,distance_x,ybin,-distance_y,distance_y)
    
    # Fill events for which the tracking notes a hit
    MIMOSA_TH2D       = ROOT.TH2D("tracking_particles", "Tracking particles",xbin,-distance_x,distance_x,ybin,-distance_y,distance_y)
    
    t_calc.fillEfficiencyObjects(LGAD_TH2D, MIMOSA_TH2D, tracking, pulse_amplitude, distance_x, distance_y, xbin, ybin)

    # Create efficiency and inefficiency objects
    th_name = "_" + str(md.getBatchNumber()) + "_" + md.chan_name
    efficiency_TEff = ROOT.TEfficiency(LGAD_TH2D, MIMOSA_TH2D)
    inefficiency_TH2D = ROOT.TH2D("inefficiency"+th_name, "inefficiency",xbin,-distance_x,distance_x,ybin,-distance_y,distance_y)

    # Total entries refer to pass events, that is number of recorded pixels on the sensor given a hit
    # in the MIMOSA. This number is used for both efficiency and inefficiency plots.
    totalEntries = efficiency_TEff.GetPassedHistogram().GetEntries()

    # Draw the TEfficiency object, and rescale it
    efficiency_TEff.Draw("COLZ0")
    canvas.Update()
    efficiency_TH2D = efficiency_TEff.GetPaintedHistogram()
    efficiency_TH2D.SetName("efficiency"+th_name)
    efficiency_TH2D.SetTitle("efficiency")
    efficiency_TH2D.Scale(100)

    # PROJECTION X AND Y #
    
    # Projection Y have extended limits (with larger bin number)
    # to preserve the same length of the window, for better comparison with projection X.
    # The window is then reduced to match the bin number
    
    projectionX_th1d = ROOT.TProfile("projection_x"+th_name, "projection_x", xbin,-distance_x,distance_x)
    projectionY_th1d = ROOT.TProfile("projection_y"+th_name, "projection_y", xbin,-distance_x,distance_x)
    
    t_calc.fillInefficiencyAndProjectionObjects(efficiency_TH2D, inefficiency_TH2D, projectionX_th1d, projectionY_th1d, xbin, ybin)

    efficiency_TH2D.SetAxisRange(percentage_efficiency, 100, "Z")
    printTHPlot(efficiency_TH2D, totalEntries)
    
    inefficiency_TH2D.SetAxisRange(0, 100-percentage_efficiency, "Z")
    printTHPlot(inefficiency_TH2D, totalEntries)

    # Create projection plots for single pad only
    produceProjectionPlots(projectionX_th1d, projectionY_th1d)
示例#10
0
def createArrayPadGraphs(distance_x, distance_y):
    
    if not t_calc.sensorIsAnArrayPad():
        return 0
    
    distance_x *= 2
    distance_y *= 2
    
    xbin = int(2*distance_x/bin_size)
    ybin = int(2*distance_y/bin_size)
    
    # The binning for the timing resolution is decreased
    xbin_timing = int(xbin/bin_timing_decrease)
    ybin_timing = int(ybin/bin_timing_decrease)
    
    arrayPadChannels = t_calc.getArrayPadChannels()
    md.setChannelName(arrayPadChannels[0])
    
    th_name = "_"+str(md.getBatchNumber())+"_"+md.chan_name
    
    pulse_amplitude_TH2D   = ROOT.TProfile2D("pulse_amplitude"+th_name, "pulse_amplitude", xbin, -distance_x, distance_x, ybin, -distance_y, distance_y)
    gain_TH2D              = ROOT.TProfile2D("gain"+th_name, "gain", xbin, -distance_x, distance_x, ybin, -distance_y, distance_y)
    rise_time_TH2D         = ROOT.TProfile2D("rise_time"+th_name, "rise_time", xbin, -distance_x, distance_x, ybin, -distance_y, distance_y)
    
    timing_peak_TH2D       = ROOT.TH2D("timing_peak"+th_name, "timing_peak", xbin_timing, -distance_x, distance_x, ybin_timing, -distance_y, distance_y)
    timing_cfd_TH2D        = ROOT.TH2D("timing_cfd"+th_name, "timing_cfd", xbin_timing, -distance_x, distance_x, ybin_timing, -distance_y, distance_y)
    
    efficiency_TH2D        = ROOT.TH2D("efficiency"+th_name, "efficiency", xbin,-distance_x,distance_x,ybin,-distance_y,distance_y)
    inefficiency_TH2D      = ROOT.TH2D("inefficiency"+th_name, "inefficiency", xbin,-distance_x,distance_x,ybin,-distance_y,distance_y)
    
    TH2D_objects_list = [pulse_amplitude_TH2D, gain_TH2D, rise_time_TH2D, timing_peak_TH2D, timing_cfd_TH2D, efficiency_TH2D, inefficiency_TH2D]
    
    print "\nArray-pad", md.getSensor(), "\n"
    
    for TH2D_object in TH2D_objects_list:
        for index in range(0, len(arrayPadChannels)):
            
            # Omit the lower-left pad for timing resolution only for W4-S215 B207 Sep TB17
            if TH2D_object.GetName().find("timing") != -1 and arrayPadChannels[index] == "chan3":
                continue

            t_calc.importAndAddHistogram(TH2D_object, index)


    # Change the file names of the exported files (array)
    t_calc.setArrayPadExportBool(True)

    setPlotLimitsAndPrint(TH2D_objects_list)
示例#11
0
def exportImportROOTHistogram(group,
                              category,
                              subcategory="",
                              chan2="",
                              graphList=0):

    fileName = getFileNameForHistogram(group, category, subcategory, chan2)
    fileName = fileName.replace(getPlotsSourceFolder(),
                                getHistogramsSourceFolder())
    fileName = fileName.replace(".pdf", ".root")

    if graphList != 0:

        fileObject = ROOT.TFile(fileName, "RECREATE")
        graphList.Write()
        fileObject.Close()

    else:
        th_name = "_" + str(md.getBatchNumber()) + "_" + md.chan_name
        objectName = category + th_name

        if subcategory != "":
            objectName = category + "_" + subcategory + th_name

        if chan2 != "":
            objectName += "_" + chan2

        exists = os.path.isfile(fileName)

        if exists:
            fileObject = ROOT.TFile(fileName)
            histogram = fileObject.Get(objectName)

            histogram.SetDirectory(
                0
            )  # Disconnect the ownership of the TFile object from the imported TH-object
            fileObject.Close()
            return histogram

        else:
            print fileName, "does not exist!\n"
            return exists
def getArrayPadChannels():

    batchCategory = md.getBatchNumber() / 100

    if batchCategory == 1:
        channels = ["chan4", "chan5", "chan6", "chan7"]

    elif batchCategory == 2:
        channels = ["chan3", "chan5", "chan6", "chan7"]

    elif batchCategory == 3:
        channels = ["chan4", "chan5"]

    elif batchCategory == 4:
        channels = ["chan1", "chan5", "chan6", "chan7"]

    elif batchCategory == 5 or batchCategory == 7:
        channels = ["chan5", "chan6", "chan7"]

    elif batchCategory == 6:
        channels = ["chan0", "chan1"]

    return channels
def rotateSensor(tracking):

    theta = 0.0

    sensor = md.getSensor()
    batchGroup = md.getBatchNumber() / 100

    # Rotation for W4-S204_6e14

    if sensor == "W9-LGA35" and batchGroup == 2:

        theta = 0.1

    elif sensor == "W4-LG12" and batchGroup == 2:

        theta = 0

    elif sensor == "W4-RD01":

        theta = 0.0

        if batchGroup == 3:
            theta = 0.2

    elif sensor == "W4-S1022":

        theta = 0.2

        if batchGroup == 5:

            theta = 0.1

        elif batchGroup == 7:

            theta = 0.1

    elif sensor == "W4-S1061":

        theta = 0.2
        if batchGroup == 5:
            theta = 0.15

        elif batchGroup == 7:
            theta = 0.15

    elif sensor == "W4-S203":

        theta = -0.1
        if batchGroup == 5:
            theta = -0.2

        elif batchGroup == 7:
            theta = -0.5

    elif sensor == "W4-S204_6e14":

        theta = 4.45

    elif sensor == "W4-S215":

        theta = 0.55
        if batchGroup == 5:
            theta = 0.8
        elif batchGroup == 7:
            theta = 0.8

    if theta != 0.0:

        # Use the rotation matrix around z
        theta *= np.pi / 180.0
        tracking["X"] = np.multiply(tracking["X"],
                                    np.cos(theta)) - np.multiply(
                                        tracking["Y"], np.sin(theta))
        tracking["Y"] = np.multiply(tracking["X"],
                                    np.sin(theta)) + np.multiply(
                                        tracking["Y"], np.cos(theta))
def getCenterOfSensor(pulse_amplitude, tracking):

    bin_size = 18.4

    # This has to be changed to match the MIMOSA! These are ranges in um.
    [xmin, xmax, ymin, ymax, minEntries] = [-7000, 8000, 9000, 16000, 5]

    # Choose ranges to center the DUTs depending on batch (the SiPM is larger, therefore the mean values of it are not exact)
    if md.getBatchNumber() == 101 or md.getBatchNumber() == 207:
        [xmin, xmax, ymin, ymax, minEntries] = [-1500, 1500, 11500, 14500, 8]

    elif md.getBatchNumber() == 306:
        [xmin, xmax, ymin, ymax, minEntries] = [-4500, -1000, 11000, 14000, 20]

    elif md.getBatchNumber() == 401:
        [xmin, xmax, ymin, ymax, minEntries] = [-4000, -1200, 10500, 13500, 5]

    elif md.getBatchNumber() == 507 or md.getBatchNumber() == 707:
        [xmin, xmax, ymin, ymax, minEntries] = [-3000, 800, 10000, 13500, 5]
        if md.getBatchNumber() == 707:
            bin_size *= 2

    elif md.getBatchNumber() == 601:
        [xmin, xmax, ymin, ymax, minEntries] = [-1500, 500, 10000, 13000, 20]

    xbin = int((xmax - xmin) / bin_size)
    ybin = int((ymax - ymin) / bin_size)

    passed_th2d = ROOT.TH2D("passed", "passed", xbin, xmin, xmax, ybin, ymin,
                            ymax)
    total_th2d = ROOT.TH2D("total", "total", xbin, xmin, xmax, ybin, ymin,
                           ymax)

    # Fill the events
    for event in range(0, len(tracking)):
        if tracking['X'][event] > -9990 and tracking['Y'][event] > -9990:
            total_th2d.Fill(tracking['X'][event], tracking['Y'][event], 1)
            if pulse_amplitude[event] != 0:
                passed_th2d.Fill(tracking['X'][event], tracking['Y'][event], 1)

    # Remove bins with less than some entries
    for i in range(1, xbin + 1):
        for j in range(1, ybin + 1):
            bin = passed_th2d.GetBin(i, j)
            num_passed = float(passed_th2d.GetBinContent(bin))
            num_total = float(total_th2d.GetBinContent(bin))

            if num_total != 0.0:
                if 0.8 > (num_passed / num_total):
                    passed_th2d.SetBinContent(bin, 0)
                    total_th2d.SetBinContent(bin, 0)

            if num_total < minEntries:
                passed_th2d.SetBinContent(bin, 0)
                total_th2d.SetBinContent(bin, 0)

    passed_th2d.ResetStats()
    total_th2d.ResetStats()

    efficiency = ROOT.TEfficiency(passed_th2d, total_th2d)
    efficiency.Draw("COLZ")
    canvas_center.Update()
    efficiency_th2d = efficiency.GetPaintedHistogram()

    # Calculate the mean value for each DUT
    position_temp = np.array(
        [efficiency_th2d.GetMean(),
         efficiency_th2d.GetMean(2)])

    line_distance = 700
    line_x = ROOT.TLine(position_temp[0], position_temp[1] - line_distance,
                        position_temp[0], position_temp[1] + line_distance)
    line_y = ROOT.TLine(position_temp[0] - line_distance, position_temp[1],
                        position_temp[0] + line_distance, position_temp[1])

    # Print the graph to estimate if the positions are correct
    canvas_center.Clear()
    efficiency_th2d.SetStats(1)
    efficiency_th2d
    efficiency_th2d.Draw("COLZ")
    line_x.Draw("same")
    line_y.Draw("same")
    canvas_center.Update()

    filePath = dm.getSourceFolderPath() + "/position_" + str(md.getBatchNumber(
    )) + "_" + md.getSensor() + "_" + md.chan_name + ".pdf"

    # If one wants to see where the center is, comment this line and change filePath
    #canvas_center.Print(filePath)

    canvas_center.Clear()

    return position_temp
def printWaveform(runNumber, sensor, event = 0):
    
    # Define global variables
    md.defineRunInfo(md.getRowForRunNumber(runNumber))
    dm.defineDataFolderPath()
    chan = md.getChannelNameForSensor(sensor)
    md.setChannelName(chan)
    
    # Create TMultigraph and define underlying graphs
    multi_graph = ROOT.TMultiGraph()
    canvas = ROOT.TCanvas("Waveforms","Waveforms")
    legend = ROOT.TLegend(0.65, 0.9, 0.9, 0.6)

    # Import the event from the oscilloscope file
    data_import = dm.getOscilloscopeData(event, event+1)
    data = -data_import[chan][0]
    
    # Set find noise and pedestal and define the threshold of finding signals
    timeScope = 0.1
    N = 4.27
    noise, pedestal = p_calc.calculateNoiseAndPedestal(data)
    threshold = N * noise + pedestal

    # Define point difference for second degree fit and maximum signal limit (saturated signals)
    signal_limit_DUT = 0.3547959
    point_difference = 2
    
    # Calculate pulse characteristics (based on the methods from pulse_calculations.py)
    peak_value, peak_time, poly_fit = p_calc.calculatePulseAmplitude(data, pedestal, signal_limit_DUT, True)
    rise_time, cfd, linear_fit, linear_fit_indices = p_calc.calculateRiseTime(data, pedestal, True)
    charge = p_calc.calculateCharge(data, pedestal)
    point_count = p_calc.calculatePoints(data, threshold)
    max_sample = np.amax(data) - pedestal


    # Define ROOT objects for each type of graph
    graph_waveform = ROOT.TGraph(len(data))
    graph_threshold = ROOT.TGraph(2)
    graph_pulse_amplitude = ROOT.TGraph(2)
    graph_max_sample = ROOT.TGraph(2)
    graph_cfd = ROOT.TGraph(2)
    graph_peak_time = ROOT.TGraph(2)
    graph_10 = ROOT.TGraph(2)
    graph_90 = ROOT.TGraph(2)
    graph_pedestal = ROOT.TGraph(2)
    graph_noise = ROOT.TGraph(2)
    graph_linear_fit = ROOT.TGraph(len(linear_fit_indices))
    graph_2nd_deg_fit = ROOT.TGraph(point_difference*2+1)

   
    # Find points to draw the shade showing the charge
    pedestal_points = p_calc.getConsecutiveSeries(data, np.argwhere(data > pedestal).flatten())
    n = len(pedestal_points)+1
    charge_fill = ROOT.TGraph(2*n)
    fillOnce = True

    # Draw the waveform and the charge fill
    for index in range(0, len(data)):
        
        graph_waveform.SetPoint(index, index*0.1, data[index]*1000)

        if index > pedestal_points[0]-1 and fillOnce:

            for i in range(0, n):

                charge_fill.SetPoint(i,   0.1 * (i+index),     data[i+index] * 1000)
                charge_fill.SetPoint(n+i, 0.1 * (n-i+index-1), pedestal * 1000)

            fillOnce = False


    # Draw the second degree fit
    first_index = np.argmax(data) - point_difference
    last_index = np.argmax(data) + point_difference
    poly_fit_range = np.arange(first_index, last_index, 0.1)

    i = 0
    for index in range(0, len(poly_fit_range)):
        time = poly_fit_range[index]*timeScope
        value = poly_fit[0] * np.power(time, 2) + poly_fit[1] * time + poly_fit[2] + pedestal
        graph_2nd_deg_fit.SetPoint(i, time, value*1000)
        i += 1
    
    # Draw the linear fit
    i = 0
    for index in range(0, len(linear_fit_indices)):
        time = linear_fit_indices[index]*timeScope
        value = linear_fit[0]*time + linear_fit[1]
        graph_linear_fit.SetPoint(i, time, value*1000)
        i+=1

    # Draw lines (by setting two points at the beginning and the end)
    graph_threshold.SetPoint(0,0, threshold*1000)
    graph_threshold.SetPoint(1,1002, threshold*1000)

    graph_noise.SetPoint(0,0, (noise+pedestal)*1000)
    graph_noise.SetPoint(1,1002, (noise+pedestal)*1000)

    graph_pedestal.SetPoint(0,0, pedestal*1000)
    graph_pedestal.SetPoint(1,1002, pedestal*1000)
    
    graph_pulse_amplitude.SetPoint(0,0, peak_value*1000)
    graph_pulse_amplitude.SetPoint(1,1002, peak_value*1000)
    
    graph_max_sample.SetPoint(0,0, max_sample*1000)
    graph_max_sample.SetPoint(1,1002, max_sample*1000)
    
    graph_cfd.SetPoint(0, cfd, -30)
    graph_cfd.SetPoint(1, cfd, 500)

    graph_peak_time.SetPoint(0, peak_time, -30)
    graph_peak_time.SetPoint(1, peak_time, 500)

    graph_10.SetPoint(0,0, peak_value*0.1*1000)
    graph_10.SetPoint(1,1002, peak_value*0.1*1000)
    graph_90.SetPoint(0,0, peak_value*0.9*1000)
    graph_90.SetPoint(1,1002, peak_value*0.9*1000)


    # Define line and marker attributes
    graph_waveform.SetLineWidth(2)
    graph_waveform.SetMarkerStyle(6)
    graph_waveform.SetLineColor(2)

    graph_linear_fit.SetLineWidth(3)
    graph_linear_fit.SetLineColorAlpha(1, 0.75)
    graph_linear_fit.SetMarkerColorAlpha(1, 0.0)
    
    graph_2nd_deg_fit.SetLineWidth(3)
    graph_2nd_deg_fit.SetLineColorAlpha(3, 0.75)
    graph_2nd_deg_fit.SetMarkerColorAlpha(1, 0.0)

    graph_cfd.SetLineStyle(7)
    graph_cfd.SetLineColor(8)
   
    graph_pulse_amplitude.SetLineColor(4)

    graph_peak_time.SetLineColor(8)
    graph_pedestal.SetLineColor(6)
    graph_noise.SetLineColor(7)
    graph_threshold.SetLineColor(1)
    graph_max_sample.SetLineColor(2)
    graph_10.SetLineColor(7)
    graph_90.SetLineColor(7)
    charge_fill.SetFillStyle(3013)
    charge_fill.SetFillColor(4)
    

    # Add the graphs to multigraph
    multi_graph.Add(graph_waveform)
    multi_graph.Add(graph_noise)
    multi_graph.Add(graph_threshold)
    multi_graph.Add(graph_2nd_deg_fit)
    multi_graph.Add(graph_linear_fit)
    multi_graph.Add(graph_pulse_amplitude)
    multi_graph.Add(graph_max_sample)
    multi_graph.Add(graph_10)
    multi_graph.Add(graph_90)
    multi_graph.Add(graph_cfd)
    multi_graph.Add(graph_peak_time)
    multi_graph.Add(graph_pedestal)
    multi_graph.Add(charge_fill, "f")

    
    # Add the information to a legend box
    legend.AddEntry(graph_waveform, "Waveform " + md.getSensor(), "l")
    legend.AddEntry(graph_noise, "Noise: "+str(noise*1000)[:4]+" mV", "l")
    legend.AddEntry(graph_pedestal, "Pedestal: "+str(pedestal*1000)[:4]+" mV", "l")
    legend.AddEntry(graph_threshold, "Threshold: "+str(threshold*1000)[:5]+" mV", "l")
    legend.AddEntry(graph_max_sample, "Max sample: "+str(max_sample*1000)[:5]+" mV", "l")
    legend.AddEntry(graph_waveform, "Points above threshold: "+str(point_count), "l")
    legend.AddEntry(graph_pulse_amplitude, "Pulse amplitude: "+str(peak_value[0]*1000)[:5]+" mV", "l")
    legend.AddEntry(graph_peak_time, "Time at peak: " + str(peak_time[0])[0:5] + " ns", "l")
    legend.AddEntry(graph_linear_fit, "Rise time: "+str(rise_time*1000)[:5]+" ps", "l")
    legend.AddEntry(graph_90, "10% and 90% limit", "l")
    legend.AddEntry(graph_cfd, "CFD 0.5: " + str(cfd)[0:5] + " ns", "l")
    legend.AddEntry(charge_fill, "Charge: "+str(charge*10**15)[:5]+" fC", "f")


    # Define the titles and draw the graph
    xAxisTitle = "Time [ns]"
    yAxisTitle = "Voltage [mV]"
    headTitle = "Waveform " + md.getSensor()
    multi_graph.Draw("ALP")
    legend.Draw()
    multi_graph.SetTitle(headTitle)
    multi_graph.GetXaxis().SetTitle(xAxisTitle)
    multi_graph.GetYaxis().SetTitle(yAxisTitle)

    # Set ranges on axes
    multi_graph.GetYaxis().SetRangeUser(-30,350)
    multi_graph.GetXaxis().SetRangeUser(cfd-5,cfd+5)


    # Export the PDF file
    fileName = dm.getPlotsSourceFolder()+"/waveforms/waveform"+"_"+str(md.getBatchNumber())+"_"+str(runNumber)+"_event_"+str(event)+"_"+str(sensor)+".pdf"

    canvas.Print(fileName)

    print "PDF produced at", fileName+"."
示例#16
0
def getLimitsForEachSensorAndBatch():

    if md.getSensor() == "50D-GBGR2" and md.getBatchNumber() == 108:
        
        # not used
        gain_limits = [20, 70]
        pulse_amplitude_limits = [100, 160]
        rise_time_limits = [400, 460]
        
        timing_res_cfd_limits = [22, 40]
        timing_res_peak_limits = [27, 47]
    
    
    elif md.getSensor() == "50D-GBGR2" and md.getBatchNumber() == 207:
        
        gain_limits = [20, 55]
        pulse_amplitude_limits = [80, 150]
        rise_time_limits = [415, 450]
        
        # not used
        timing_res_cfd_limits = [22, 60]
        timing_res_peak_limits = [25, 65]
    
    elif md.getSensor() == "W4-LG12" and md.getBatchNumber() == 108:
        
        # not used
        gain_limits = [20, 90]
        pulse_amplitude_limits = [60, 160]
        rise_time_limits = [520, 560]
        
        timing_res_cfd_limits = [18, 32]
        timing_res_peak_limits = [30, 46]
    
    elif md.getSensor() == "W4-LG12" and md.getBatchNumber() == 207:
        
        gain_limits = [30, 90]
        pulse_amplitude_limits = [60, 155]
        rise_time_limits = [520, 565]
        
        # not used
        timing_res_cfd_limits = [20, 70]
        timing_res_peak_limits = [25, 75]
    
    elif md.getSensor() == "W4-RD01" and md.getBatchNumber() == 306:
        
        gain_limits = [340, 500]
        pulse_amplitude_limits = [160, 310]
        rise_time_limits = [820, 870]
        
        timing_res_peak_limits = [58, 80]
        timing_res_cfd_limits = [20, 40]
    
    elif md.getSensor() == "W4-RD01" and md.getBatchNumber() == 601:
        
        gain_limits = [330, 440]
        pulse_amplitude_limits = [140, 240]
        rise_time_limits = [1220, 1300]
        
        timing_res_peak_limits = [70, 130]
        timing_res_cfd_limits = [30, 75]
    
    elif md.getSensor() == "W4-S1022" and md.getBatchNumber() == 306:
        
        gain_limits = [20, 38]
        pulse_amplitude_limits = [35, 75]
        rise_time_limits = [600, 680]
        
        timing_res_peak_limits = [90, 160]
        timing_res_cfd_limits = [30, 80]
    
    elif md.getSensor() == "W4-S1022" and md.getBatchNumber() == 507:
        
        gain_limits = [40, 85]
        pulse_amplitude_limits = [80, 160]
        rise_time_limits = [505, 545]
        
        timing_res_peak_limits = [90, 160]
        timing_res_cfd_limits = [30, 80]
    
    elif md.getSensor() == "W4-S1022" and md.getBatchNumber() == 707:
        
        gain_limits = [35, 85]
        pulse_amplitude_limits = [80, 160]
        rise_time_limits = [525, 565]
        
        timing_res_cfd_limits = [30, 80]
        timing_res_peak_limits = [90, 160]
    
    elif md.getSensor() == "W4-S1061" and md.getBatchNumber() == 306:
        
        gain_limits = [35, 65]
        pulse_amplitude_limits = [85, 145]
        rise_time_limits = [490, 530]
        
        timing_res_cfd_limits = [30, 80]
        timing_res_peak_limits = [90, 160]
    
    elif md.getSensor() == "W4-S1061" and md.getBatchNumber() == 507:
        
        gain_limits = [35, 65]
        pulse_amplitude_limits = [80, 140]
        rise_time_limits = [535, 570]
        
        timing_res_cfd_limits = [30, 80]
        timing_res_peak_limits = [90, 160]
    
    elif md.getSensor() == "W4-S1061" and md.getBatchNumber() == 707:
        
        gain_limits = [30, 80]
        pulse_amplitude_limits = [70, 150]
        rise_time_limits = [540, 575]
        
        timing_res_cfd_limits = [30, 80]
        timing_res_peak_limits = [90, 160]
    
    elif md.getSensor() == "W4-S203" and md.getBatchNumber() == 306:
        
        gain_limits = [40, 70]
        pulse_amplitude_limits = [90, 150]
        rise_time_limits = [515, 540]
        
        timing_res_cfd_limits = [30, 80]
        timing_res_peak_limits = [90, 160]
    
    elif md.getSensor() == "W4-S203" and md.getBatchNumber() == 507:
        
        gain_limits = [35, 70]
        pulse_amplitude_limits = [50, 100]
        rise_time_limits = [680, 780]
        
        timing_res_cfd_limits = [30, 80]
        timing_res_peak_limits = [90, 160]
    
    elif md.getSensor() == "W4-S203" and md.getBatchNumber() == 707:
        
        gain_limits = [40, 80]
        pulse_amplitude_limits = [50, 110]
        rise_time_limits = [725, 830]
        
        timing_res_cfd_limits = [30, 80]
        timing_res_peak_limits = [90, 160]
    
    elif md.getSensor() == "W4-S204_6e14" and md.getBatchNumber() == 507:
        
        gain_limits = [5, 26]
        pulse_amplitude_limits = [40, 80]
        rise_time_limits = [315, 390]
        
        timing_res_cfd_limits = [36, 60]
        timing_res_peak_limits = [44, 65]
    
    elif md.getSensor() == "W4-S204_6e14" and md.getBatchNumber() == 707:
        
        gain_limits = [8, 28]
        pulse_amplitude_limits = [40, 90]
        rise_time_limits = [315, 390]
        
        timing_res_cfd_limits = [34, 48]
        timing_res_peak_limits = [40, 60]
    
    elif md.getSensor() == "W4-S215" and md.getBatchNumber() == 207:
        
        gain_limits = [70, 130]
        pulse_amplitude_limits = [160, 260]
        rise_time_limits = [490, 540]
        
        timing_res_cfd_limits = [25, 45]
        timing_res_peak_limits = [25, 50]
    
    elif md.getSensor() == "W4-S215" and md.getBatchNumber() == 507:
        
        gain_limits = [110, 210]
        pulse_amplitude_limits = [200, 330]
        rise_time_limits = [520, 590]
        
        # not used
        timing_res_cfd_limits = [20, 70]
        timing_res_peak_limits = [30, 80]
    
    elif md.getSensor() == "W4-S215" and md.getBatchNumber() == 707:
        
        gain_limits = [100, 190]
        pulse_amplitude_limits = [140, 240]
        rise_time_limits = [700, 825]
        
        # not used
        timing_res_cfd_limits = [20, 70]
        timing_res_peak_limits = [30, 80]
    
    elif md.getSensor() == "W9-LGA35" and md.getBatchNumber() == 108:
        
        # not used
        gain_limits = [30, 50]
        pulse_amplitude_limits = [60, 110]
        rise_time_limits = [415, 455]
        
        timing_res_cfd_limits = [20, 40]
        timing_res_peak_limits = [24, 46]
    
    elif md.getSensor() == "W9-LGA35" and md.getBatchNumber() == 207:
        
        gain_limits = [20, 45]
        pulse_amplitude_limits = [50, 115]
        rise_time_limits = [415, 455]
        
        # not used
        timing_res_cfd_limits = [20, 70]
        timing_res_peak_limits = [25, 75]

    # This method is modular to adapt for other batches
    else:
        
        th_name = "_"+str(md.getBatchNumber())+"_"+md.chan_name
        
        pulse_amplitude_mean =  dm.exportImportROOTHistogram("pulse", "pulse_amplitude").GetFunction("Fitfcn_pulse_amplitude"+th_name).GetParameter(1)
        gain_mean =             dm.exportImportROOTHistogram("pulse", "charge").GetFunction("Fitfcn_charge"+th_name).GetParameter(1)/md.getChargeWithoutGainLayer()
        
        rise_time_mean = dm.exportImportROOTHistogram("pulse", "rise_time").GetFunction("gaus").GetParameter(1)
        timing_res_peak_mean = np.sqrt(np.power(dm.exportImportROOTHistogram("timing", "normal", "peak").GetFunction("gaus").GetParameter(2),2) - np.power(md.getSigmaSiPM(),2))
        timing_res_cfd_mean = np.sqrt(np.power(dm.exportImportROOTHistogram("timing", "normal", "cfd").GetFunction("gaus").GetParameter(2), 2) - np.power(md.getSigmaSiPM(), 2))
        
        [pulse_amplitude_limits, gain_limits, rise_time_limits, timing_res_peak_limits, timing_res_cfd_limits] = [[max(pulse_amplitude_mean-50,0), pulse_amplitude_mean+50], [max(gain_mean-30, 0), gain_mean+30], [max(rise_time_mean-30, 0), rise_time_mean+30], [max(timing_res_peak_mean-50, 0), timing_res_peak_mean+50], [max(timing_res_cfd_mean-50, 0), timing_res_cfd_mean+50]]
    
    
    limits_graph = [pulse_amplitude_limits, gain_limits, rise_time_limits, timing_res_peak_limits, timing_res_cfd_limits]

    return limits_graph
示例#17
0
def declareTCanvas():

    global canvas, canvas_projection
    
    canvas = ROOT.TCanvas("Tracking "+str(md.getBatchNumber()), "tracking")
    canvas_projection = ROOT.TCanvas("Projection "+str(md.getBatchNumber()), "projection")
示例#18
0
def trackingPlots():
    
    global var_names
    
    startTime = dm.getTime()
    
    print "\nStart TRACKING analysis, batches:", md.batchNumbers, "\n"
    
    for batchNumber in md.batchNumbers:
        
        startTimeBatch = dm.getTime()
        runNumbers = md.getAllRunNumbers(batchNumber)
        
        # Omit batches with less than 3 runs
        if len(runNumbers) < 3:
            
            print "Batch", batchNumber, "omitted, < 3 runs.\n"
            continue
        
        print "BATCH", batchNumber, "\n"
    
        var_names = [["pulse", "pulse_amplitude"], ["pulse", "charge"], ["pulse", "rise_time"], ["timing", "normal_peak"], ["timing", "normal_cfd"]]
        
        numpy_arrays = [np.empty(0, dtype = dm.getDTYPE(batchNumber)) for _ in range(len(var_names))]
        numpy_arrays.append(np.empty(0, dtype = dm.getDTYPETracking()))
        
        max_sample = np.empty(0, dtype = dm.getDTYPE(batchNumber))
        
        for runNumber in runNumbers:
            
            md.defineRunInfo(md.getRowForRunNumber(runNumber))
            
            # Produce timing resolution files if they not exist
            if not dm.checkIfROOTDataFileExists("timing", "normal_peak"):
                t_calc.createTimingFiles(batchNumber)
            
            if not dm.checkIfFileAvailable("tracking"):
                continue
        
            tracking_run = dm.exportImportROOTData("tracking", "tracking")
            
            # This strips the event number to match the ones with the tracking. It assumes that the tracking have fewer number of events than the oscilloscope events.
            for index in range(0, len(var_names)):
                numpy_arrays[index] = np.concatenate((numpy_arrays[index], np.take(dm.exportImportROOTData(var_names[index][0], var_names[index][1]), np.arange(0, len(tracking_run)))), axis=0)
            
            max_sample = np.concatenate((max_sample, np.take(dm.exportImportROOTData("pulse", "max_sample"), np.arange(0, len(tracking_run)))), axis=0)
            
            
            # Concatenate tracking arrays
            numpy_arrays[-1] = np.concatenate((numpy_arrays[-1], tracking_run), axis=0)
    
    
        [pulse_amplitude, gain, rise_time, time_difference_peak, time_difference_cfd, tracking] = [i for i in numpy_arrays]
        
        # This checks if the position file exists, otherwise it will create it
        if not dm.checkIfROOTDataFileExists("tracking", "position"):
            t_calc.calculateCenterOfSensorPerBatch(pulse_amplitude, tracking)
    
        declareTCanvas()
        defineBinSizes()

        if md.getBatchNumber()/100 == 7:
            updateBinSize(1.5)

        t_calc.setArrayPadExportBool(False)

        createSinglePadGraphs(numpy_arrays, max_sample)
        
        createArrayPadGraphs(distance_x, distance_y)
        
        print "\nDone with batch", batchNumber, "Time analysing: "+str(md.dm.getTime()-startTimeBatch)+"\n"
                                
                                
    print "\nDone with TRACKING analysis. Time analysing: "+str(md.dm.getTime()-startTime)+"\n"
def producePulsePlots(numpy_variables):

    [
        noise, pedestal, pulse_amplitude, rise_time, charge, cfd, peak_time,
        points, max_sample
    ] = [i for i in numpy_variables]

    dm.changeIndexNumpyArray(noise, 1000.0)
    dm.changeIndexNumpyArray(pedestal, -1000.0)
    dm.changeIndexNumpyArray(pulse_amplitude, -1000.0)
    dm.changeIndexNumpyArray(rise_time, 1000.0)
    dm.changeIndexNumpyArray(charge, 10**15)
    dm.changeIndexNumpyArray(max_sample, -1000.0)

    print "\nBATCH", md.getBatchNumber(), "\n"

    for chan in pulse_amplitude.dtype.names:

        md.setChannelName(chan)

        if md.sensor != "" and md.getSensor() != md.sensor:
            continue

        # if a fit fails, slightly change the bin number
        pulse_amplitude_bins = 150
        point_count_limit = 50
        charge_pulse_bins = 110
        rise_time_bins = 150
        charge_max = 150

        # This is a limit for the point count, to increase it
        if md.getSensor() == "SiPM-AFP" or md.getSensor() == "W4-RD01":
            point_count_limit = 100
            charge_max = 500

        print md.getSensor(), "\n"

        noise_avg_std = [np.average(noise[chan]), np.std(noise[chan])]
        pedestal_avg_std = [np.average(pedestal[chan]), np.std(pedestal[chan])]

        noise_ranges, pedestal_ranges = getRanges(noise_avg_std,
                                                  pedestal_avg_std, 6)

        # Create TH objects with properties to be analyzed

        th_name = "_" + str(md.getBatchNumber()) + "_" + md.chan_name

        noise_TH1F = ROOT.TH1F("noise" + th_name, "noise", 300,
                               noise_ranges[0], noise_ranges[1])
        pedestal_TH1F = ROOT.TH1F("pedestal" + th_name, "pedestal", 300,
                                  pedestal_ranges[0], pedestal_ranges[1])

        pulse_amplitude_TH1F = ROOT.TH1F("pulse_amplitude" + th_name,
                                         "pulse_amplitude",
                                         pulse_amplitude_bins, 0, 500)
        rise_time_TH1F = ROOT.TH1F("rise_time" + th_name, "rise_time",
                                   rise_time_bins, 0, 4000)
        charge_TH1F = ROOT.TH1F("charge" + th_name, "charge",
                                charge_pulse_bins, 0, charge_max)

        # Additional TH objects for inspection of signals
        peak_time_TH1F = ROOT.TH1F("peak_time" + th_name, "peak_time", 100, 0,
                                   100)
        cfd_TH1F = ROOT.TH1F("cfd" + th_name, "cfd", 100, 0, 100)
        point_count_TH1F = ROOT.TH1F("point_count" + th_name, "point_count",
                                     point_count_limit, 0, point_count_limit)
        max_sample_TH1F = ROOT.TH1F("max_sample" + th_name, "max_sample", 100,
                                    0, 400)
        max_sample_vs_points_threshold_TH2F = ROOT.TH2F(
            "max_sample_vs_point_count" + th_name, "max_sample_vs_point_count",
            point_count_limit, 0, point_count_limit, 100, 0, 400)

        TH1_objects = [
            noise_TH1F, pedestal_TH1F, pulse_amplitude_TH1F, rise_time_TH1F,
            charge_TH1F, peak_time_TH1F, cfd_TH1F, point_count_TH1F,
            max_sample_TH1F
        ]

        # Fill TH1 objects
        for index in range(0, len(TH1_objects)):
            for entry in range(0, len(numpy_variables[index][chan])):
                if numpy_variables[index][chan][entry] != 0:
                    TH1_objects[index].Fill(
                        numpy_variables[index][chan][entry])

        # Fill TH2 object
        for entry in range(0, len(pulse_amplitude[chan])):
            if max_sample[chan][entry] != 0 and points[chan][entry] != 0:
                max_sample_vs_points_threshold_TH2F.Fill(
                    points[entry][chan], max_sample[entry][chan])

        # Redefine ranges for noise and pedestal fits
        ranges_noise_pedestal = getRanges(noise_avg_std, pedestal_avg_std, 3)

        # Create fits
        noise_fit, pedestal_fit = makeNoisePedestalFits(
            noise_TH1F, pedestal_TH1F, ranges_noise_pedestal)
        pulse_amplitude_langaufit = makeLandauGausFit(pulse_amplitude_TH1F,
                                                      signal_limit)
        rise_time_fit = makeRiseTimeFit(rise_time_TH1F)
        charge_langaufit = makeLandauGausFit(charge_TH1F)

        # Export plots
        for TH_obj in TH1_objects:
            exportHistogram(TH_obj)

        exportHistogram(max_sample_vs_points_threshold_TH2F)
示例#20
0
def importResultsValues(sensor_data, category_subcategory):

    global oneSensorInLegend

    if category_subcategory.endswith('gain'):
        category_subcategory = category_subcategory[:-5]
        gain_category = True

    else:
        gain_category = False

    # here are imported all files, that is for each pad, temperature and bias voltage
    for batchNumber in md.getAllBatchNumbers():
        for chan in md.getAllChannelsForSensor(batchNumber, processed_sensor):

            if batchNumber not in md.getAllBatchNumberForSensor(
                    processed_sensor) or omitBadData(batchNumber,
                                                     category_subcategory):
                continue

            md.defineRunInfo(
                md.getRowForRunNumber(md.getAllRunNumbers(batchNumber)[0]))

            md.setChannelName(chan)

            if md.getDUTPos() in ["3_0", "3_1", "3_3", "8_1", "7_2", "7_3"]:
                continue

            # Define the name for the histogram, depending on type
            if category_subcategory.find(
                    "pulse_amplitude") == -1 and category_subcategory.find(
                        "charge") == -1:

                group = "timing"
                chan2 = ""
                parameter_number = 2

                if category_subcategory.find("system") != -1:
                    if md.chan_name not in [
                            "chan0", "chan1", "chan2", "chan3"
                    ]:
                        continue

                    category = "system"
                    chan2 = "chan" + str((int(md.chan_name[-1]) + 1) % 4)

                else:
                    category = "normal"

                if category_subcategory.endswith('cfd'):

                    subcategory = "cfd"

                else:

                    subcategory = "peak"

                if category_subcategory.find(
                        "rise_time") != -1 or category_subcategory.find(
                            "noise") != -1:
                    group = "pulse"
                    category = category_subcategory
                    subcategory = ""
                    chan2 = ""

                # Here, import the histogram which contain the results
                histogram = dm.exportImportROOTHistogram(
                    group, category, subcategory, chan2)

                if histogram:
                    fit_function = histogram.GetFunction("gaus")

                    if category_subcategory.find(
                            "noise") != -1 or category_subcategory.find(
                                "rise_time") != -1:
                        parameter_number = 1

                    results = [
                        fit_function.GetParameter(parameter_number),
                        fit_function.GetParError(parameter_number)
                    ]

                else:
                    continue

            # pulse and gain
            else:

                histogram = dm.exportImportROOTHistogram(
                    "pulse", category_subcategory)
                if histogram:
                    th_name = "_" + str(
                        md.getBatchNumber()) + "_" + md.chan_name
                    function_name = "Fitfcn_" + category_subcategory + th_name
                    fit_function = histogram.GetFunction(function_name)
                    try:
                        fit_function.GetTitle()
                    except:
                        continue
                    results = [
                        fit_function.GetParameter(1),
                        fit_function.GetParError(1)
                    ]
                else:
                    continue

            if category_subcategory.find(
                    "normal") != -1 or category_subcategory.find(
                        "system") != -1:

                results[0] = np.sqrt(
                    np.power(results[0], 2) - np.power(md.getSigmaSiPM(), 2))

            value_error = [results[0], results[1]]
            voltage = md.getBiasVoltage()

            # For the timing resolution vs gain, replace the bias voltage with gain
            if (category_subcategory.find("system") != -1
                    or category_subcategory.find("normal") != -1
                ) and gain_category:

                histogram = dm.exportImportROOTHistogram("pulse", "charge")
                th_name = "_" + str(md.getBatchNumber()) + "_" + md.chan_name
                function_name = "Fitfcn_" + "charge" + th_name
                fit_function = histogram.GetFunction(function_name)

                gain = fit_function.GetParameter(
                    1) / md.getChargeWithoutGainLayer()

                voltage = int(
                    gain
                )  # this takes the even number of gain (to select better values)

            temperature = str(md.getTemperature())

            DUT_pos = md.getDUTPos()

            omitRun = False

            # Among the all batches, choose one with smallest error.
            for index in range(0, len(sensor_data[temperature][DUT_pos])):
                sensor_results = sensor_data[temperature][DUT_pos][index]

                # Check if there is an earlier filled bias voltage, otherwise fill
                if voltage == sensor_results[0]:

                    omitRun = True

                    # For the same voltage, choose the one with smallest error.
                    if value_error[1] < sensor_results[1][1]:

                        sensor_data[temperature][DUT_pos][index] = [
                            voltage, value_error
                        ]

            if not omitRun:
                sensor_data[temperature][DUT_pos].append(
                    [voltage, value_error])

    oneSensorInLegend = True
def produceTimingDistributionPlotsSysEq(time_difference, category):
    
    text = "\nSYS. OF. EQS. TIME DIFFERENCE (PEAK) BATCH " + str(md.getBatchNumber()) + "\n"
  
    if category.find("cfd") != -1:
        text = text.replace("PEAK", "CFD")
    
    print text
    
    
    # TH1 objects
    time_diff_TH1F = dict()
    
    omit_batch = False

    channels_1st_oscilloscope   = ["chan0", "chan1", "chan2", "chan3"]

    sigma_convoluted            = np.zeros((4,4))
    sigma_convoluted_error      = np.zeros((4,4))
    
    # First loop, calculate the sigmas for each combination of time differences
    for chan in channels_1st_oscilloscope:
        
        md.setChannelName(chan)
    
        print md.getSensor(), "\n"
        
        # Do not consider the same channel when comparing two
        chan2_list = list(channels_1st_oscilloscope)
        chan2_list.remove(chan)
        
        # Create TH1 object
        time_diff_TH1F[chan] = dict()
        for chan2 in chan2_list:
            th_name = "_" + str(md.getBatchNumber()) + "_" + md.chan_name + "_" + chan2
            time_diff_TH1F[chan][chan2] = ROOT.TH1F(category + th_name, category, xbins, -fill_range, fill_range)
        
        # Fill TH1 object between channels in first oscilloscope
        for entry in range(0, len(time_difference[chan])):
            for index in range(0, len(chan2_list)):
                chan2 = chan2_list[index]

                if time_difference[chan][entry][0][index] != 0:
                    time_diff_TH1F[chan][chan2].Fill(time_difference[chan][entry][0][index])
    

        # Get sigma and adapt distribution curve
        for chan2 in chan2_list:
      
            # Find the maximal value
            MPV_bin = time_diff_TH1F[chan][chan2].GetMaximumBin()
            MPV_time_diff = int(time_diff_TH1F[chan][chan2].GetXaxis().GetBinCenter(MPV_bin))

            xMin = MPV_time_diff - window_range
            xMax = MPV_time_diff + window_range
            time_diff_TH1F[chan][chan2].SetAxisRange(xMin, xMax)

            # Redefine range for the fit
            sigma_window = time_diff_TH1F[chan][chan2].GetStdDev()
            mean_window = time_diff_TH1F[chan][chan2].GetMean()
            xMin = mean_window - width_selection * sigma_window
            xMax = mean_window + width_selection * sigma_window
          
            # Obtain the parameters
            time_diff_TH1F[chan][chan2].Fit("gaus", "Q", "", xMin, xMax)
            fit_function = time_diff_TH1F[chan][chan2].GetFunction("gaus")
          
            i = int(chan[-1]) % 4
            j = int(chan2[-1]) % 4
            
            try:
           
                # Get sigma between two channels
                sigma_convoluted[i][j]  = fit_function.GetParameter(2)
                sigma_convoluted_error[i][j] = fit_function.GetParError(2)
            
            except:
            
                sigma_convoluted[i][j] = sigma_convoluted[j][i] = 0
                sigma_convoluted_error[i][j] = sigma_convoluted_error[j][i] = 0

    # Second loop, check if all combined plots have at least 1000 entries
    
    for chan in channels_1st_oscilloscope:
    
        md.setChannelName(chan)
        
        # Do not consider the same channel when comparing two
        chan2_list = list(channels_1st_oscilloscope)
        chan2_list.remove(chan)
        
        for chan2 in chan2_list:

            if time_diff_TH1F[chan][chan2].GetEntries() < min_entries_per_run * len(md.getAllRunNumbers(md.getBatchNumber())):
                
                type = "peak reference"
                
                if category.find("cfd") != -1:
                    type = "cfd reference"
                
                print "Omitting batch", md.getBatchNumber(), "for", type, "time difference system plot for", md.getSensor(), "and", md.getSensor(chan2), "due to low statistics \n"
                
                omit_batch = True
                
                break

        if omit_batch:
            break

    # Solve the system in case the condition of requiring at least 1000 entries for each plots is not fulfilled
    if not omit_batch:
        sigmas_chan, sigmas_error = t_calc.solveSystemOfEqs(sigma_convoluted, sigma_convoluted_error)

        # Third loop, print the graphs together with the solutions
        for chan in channels_1st_oscilloscope:
        
            md.setChannelName(chan)
   
            chan2_list = list(channels_1st_oscilloscope)
            chan2_list.remove(chan)


            # Loop through the combinations
            for chan2 in chan2_list:

                index = int(chan[-1]) % 4
                sigma_DUT = sigmas_chan[index]
                sigma_DUT_error = sigmas_error[index]

                exportTHPlot(time_diff_TH1F[chan][chan2], [sigma_DUT, sigma_DUT_error], category, chan2)