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"
Пример #2
0
def createSinglePadGraphs(numpy_arrays, max_sample):
    
    [pulse_amplitude, gain, rise_time, time_difference_peak, time_difference_cfd, tracking] = [i for i in numpy_arrays]
    
    # Convert pulse amplitude values from [-V] to [+mV], charge from [C] to gain, rise time from [ns] to [ps]
    dm.changeIndexNumpyArray(pulse_amplitude, -1000.0)
    dm.changeIndexNumpyArray(max_sample, -1000.0)
    dm.changeIndexNumpyArray(gain, 1./(md.getChargeWithoutGainLayer()*10**-15))
    dm.changeIndexNumpyArray(rise_time, 1000.0)
    
    # Produce single pad plots
    for chan in pulse_amplitude.dtype.names:
    
        md.setChannelName(chan)
        
        if (md.getSensor() != md.sensor and md.sensor != "") or md.getSensor() == "SiPM-AFP":
            continue

        print "Single pad", md.getSensor(), "\n"

        # This function requires a ROOT file which have the center positions for each pad
        tracking_chan = t_calc.changeCenterPositionSensor(np.copy(tracking))
        
        produceTProfilePlots([np.copy(pulse_amplitude[chan]), gain[chan], rise_time[chan], time_difference_peak[chan], time_difference_cfd[chan]], max_sample[chan], tracking_chan, distance_x, distance_y)
        produceEfficiencyPlot(pulse_amplitude[chan], tracking_chan, distance_x, distance_y)
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 sensorIsAnArrayPad():

    bool = True

    if md.sensor != "":
        md.setChannelName(getArrayPadChannels()[0])

        if md.sensor != md.getSensor():
            bool = False

    return bool
def importAndAddHistogram(TH2_object, index):

    chan = getArrayPadChannels()[index]
    md.setChannelName(chan)

    category = TH2_object.GetTitle()

    subcategory = ""

    if category.find("timing") != -1:
        category, subcategory = category.split("_")

    THistogram = dm.exportImportROOTHistogram("tracking", category,
                                              subcategory)
    TH2_object.Add(THistogram)
Пример #6
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)
Пример #7
0
def getTimeDifferencePerRun(time_location):
    
    time_difference = np.zeros(len(time_location), dtype = time_location.dtype)

    SiPM_chan = md.getChannelNameForSensor("SiPM-AFP")

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

        if md.getSensor() == "SiPM-AFP":
            continue

        for event in range (0, len(time_location)):
            if time_location[SiPM_chan][event] != 0 and time_location[chan][event] != 0:
                time_difference[chan][event] = (time_location[chan][event] - time_location[SiPM_chan][event])*1000


    return time_difference
Пример #8
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
Пример #9
0
def produceResults():

    global canvas
    global processed_sensor
    global bias_voltage_max

    bias_voltage_max = 350

    categories = [
        "noise", "pulse_amplitude", "charge", "rise_time", "normal_peak",
        "system_peak", "normal_cfd", "system_cfd", "normal_peak_gain",
        "system_peak_gain", "normal_cfd_gain", "system_cfd_gain",
        "normal_peak_gain_zoom", "system_peak_gain_zoom",
        "normal_cfd_gain_zoom", "system_cfd_gain_zoom"
    ]

    canvas = ROOT.TCanvas("Results", "Results")

    sensorNames = md.getAvailableSensors()
    sensorNames.remove("SiPM-AFP")

    sensorNames.sort()

    if md.sensor != "":
        sensorNames = [md.sensor]

    resultsDict = dict()
    resultGraphs = dict()
    legend = dict()

    print "\nStart RESULTS"

    zoom = False

    # loop through each category
    for category in categories:

        print "\n", category, "\n"

        if category.endswith("zoom"):
            zoom = True
            category = category[:-5]

        category_graph = ROOT.TMultiGraph()
        legend_graph = ROOT.TLegend(0.7, 0.9, 0.9, 0.6)

        graph = dict()

        doOnce = True

        for processed_sensor in sensorNames:

            print processed_sensor

            md.defineRunInfo(
                md.getRowForRunNumber(
                    md.getRunsWithSensor(processed_sensor)[0]))
            md.setChannelName(md.getChannelNameForSensor(processed_sensor))

            graph[processed_sensor] = dict()
            sensor_data = dict()

            # Create TGraphErrors for each sensor, temperature and position (in the case of array pads)
            for temperature in md.getAvailableTemperatures():

                graph[processed_sensor][temperature] = dict()
                sensor_data[temperature] = dict()

                if processed_sensor == "W4-S204_6e14" and doOnce:
                    graph["W4-S204_6e14"]["22"] = dict()
                    graph["W4-S204_6e14"]["22"]["7_0"] = ROOT.TGraphErrors()
                    r_plot.setMarkerType(graph["W4-S204_6e14"]["22"]["7_0"],
                                         DUT_pos, temperature)
                    doOnce = False

                for DUT_pos in availableDUTPositions(processed_sensor):
                    graph[processed_sensor][temperature][
                        DUT_pos] = ROOT.TGraphErrors()
                    sensor_data[temperature][DUT_pos] = []

                    # Change each marker type and color
                    r_plot.setMarkerType(
                        graph[processed_sensor][temperature][DUT_pos], DUT_pos,
                        temperature)

            importResultsValues(sensor_data, category)

            r_plot.addValuesToGraph(
                [sensor_data, category, legend_graph, graph, category_graph])

        r_plot.drawAndExportResults(category, category_graph, legend_graph,
                                    zoom)
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)
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+"."
Пример #12
0
def printTHPlot(graphList, entries=0):

    canvas.cd()
    
    if entries == 0:
        entries = graphList.GetEntries()
    
    # Get file name and title for graph
    category = graphList.GetTitle()
    headTitle = getTitles(category)

    # Move the margins to fit the Z axis
    canvas.SetRightMargin(0.14)
    canvas.SetLeftMargin(0.11)

    # Draw graph to move and recreate the stats box
    graphList.SetStats(1)
    graphList.Draw("COLZ0")
    canvas.Update()
    stats_box = graphList.GetListOfFunctions().FindObject("stats")
    stats_box.SetX1NDC(.11)
    stats_box.SetX2NDC(.25)
    stats_box.SetY1NDC(.93)
    stats_box.SetY2NDC(.83)
    stats_box.SetOptStat(1000000010)
    graphList.SetEntries(entries)


    # Draw again to update the canvas
    graphList.SetTitle(headTitle)
    graphList.Draw("COLZ0")

    # Draw lines which selects the projection limits
    efficiency_bool = True if category.find("efficiency") != -1 and category.find("inefficiency") == -1 else False

    if efficiency_bool:
    
        # This prints the selections for the efficiency bulk calculations
        if md.checkIfArrayPad() and t_calc.array_pad_export:
            channels = t_calc.getArrayPadChannels()
        
        else:
            channels = [md.chan_name]
    
        lines = dict()
        efficiency_text = dict()
    
        for chan_2 in channels:
        
            md.setChannelName(chan_2)
            
            lines[chan_2] = t_calc.definelines(0) # the argument extends the lines in [um]
            limits, center_position = t_calc.findSelectionRange()
            
            efficiency_bulk = dm.exportImportROOTData("tracking", "efficiency")
            
            efficiency_text[chan_2] = ROOT.TLatex(center_position[0]-250,center_position[1],  "Eff = " + str(efficiency_bulk[chan_2][0])[0:5] + " \pm " + str(efficiency_bulk[chan_2][1])[0:4] + " %")

            efficiency_text[chan_2].SetNDC(False)
            if md.checkIfArrayPad():
                efficiency_text[chan_2].SetTextSize(0.02)
            else:
                efficiency_text[chan_2].SetTextSize(0.04)
            efficiency_text[chan_2].Draw()

            # Draw lines which marks the bulk
            
            # Y-lines
            lines[chan_2][0].Draw()
            lines[chan_2][1].Draw()
            
            # X-lines
            lines[chan_2][2].Draw()
            lines[chan_2][3].Draw()
            
            canvas.Update()


    # Export PDF and Histogram
    canvas.Update()
    subcategory = ""

    if category.find("timing") != -1:
        category, subcategory = category.split("_")

    fileName = dm.getFileNameForHistogram("tracking", category, subcategory)

    canvas.Print(fileName)
    dm.exportImportROOTHistogram("tracking", category, subcategory, "", graphList)
    canvas.Clear()
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)