Ejemplo n.º 1
0
    def get_direction(self):
        """Function to calculate the fibre direction based on the fibre position and the 
           determined beam center from the data

         Returns:
          dir_x (float) : x coordinate of fibre direction vector
          dir_y (float) : x coordinate of fibre direction vector
          dir_z (float) : x coordinate of fibre direction vector
          dir_error_x (float) : x coordinate uncertainty of fibre direction vector
          dir_error_x (float) : x coordinate uncertainty of fibre direction vector
          dir_error_x (float) : x coordinate uncertainty of fibre direction vector
        """

        #get fibre position of the to be measured fibre
        val = fibre_handling.FibreHandling(self.f)
        sourcepos, sourcedir = val.get_fibre_position()

        #fill beam center vector with the x, y, z coordinates determined from the data
        beam_center = ROOT.TVector3()
        beam_center.SetXYZ(self.x, self.y, self.z)

        #determine fibre direction from beam center vector and fibre position
        direction = beam_center - sourcepos
        dir_x = direction.X()
        dir_y = direction.Y()
        dir_z = direction.Z()

        #calculate uncertainty on fibre direction from uncertainty on the beam center coordinates
        dir_error_x = math.sqrt(
            math.pow((math.sqrt(
                math.pow(dir_x, 2) + math.pow(dir_y, 2) + math.pow(dir_z, 2)) -
                      math.pow(dir_x, 2) * math.pow(
                          math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                          math.pow(dir_z, 2), -0.5)) * self.x_error /
                     (math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                      math.pow(dir_z, 2)), 2) + math.pow(
                          dir_x * dir_y * math.pow(
                              math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                              math.pow(dir_z, 2), -1.5) * self.y_error, 2) +
            math.pow(
                dir_x * dir_z * math.pow(
                    math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                    math.pow(dir_z, 2), -1.5) * self.z_error, 2))
        dir_error_y = math.sqrt(
            math.pow((math.sqrt(
                math.pow(dir_x, 2) + math.pow(dir_y, 2) + math.pow(dir_z, 2)) -
                      math.pow(dir_y, 2) * math.pow(
                          math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                          math.pow(dir_z, 2), -0.5)) * self.y_error /
                     (math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                      math.pow(dir_z, 2)), 2) + math.pow(
                          dir_y * dir_x * math.pow(
                              math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                              math.pow(dir_z, 2), -1.5) * self.x_error, 2) +
            math.pow(
                dir_y * dir_z * math.pow(
                    math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                    math.pow(dir_z, 2), -1.5) * self.z_error, 2))
        dir_error_z = math.sqrt(
            math.pow((math.sqrt(
                math.pow(dir_x, 2) + math.pow(dir_y, 2) + math.pow(dir_z, 2)) -
                      math.pow(dir_z, 2) * math.pow(
                          math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                          math.pow(dir_z, 2), -0.5)) * self.z_error /
                     (math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                      math.pow(dir_z, 2)), 2) + math.pow(
                          dir_z * dir_x * math.pow(
                              math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                              math.pow(dir_z, 2), -1.5) * self.x_error, 2) +
            math.pow(
                dir_z * dir_y * math.pow(
                    math.pow(dir_x, 2) + math.pow(dir_y, 2) +
                    math.pow(dir_z, 2), -1.5) * self.y_error, 2))

        #normalise direction vector
        direction.SetMag(1.)
        dir_x = direction.X()
        dir_y = direction.Y()
        dir_z = direction.Z()

        #return direction coordinates and uncertainties
        return dir_x, dir_y, dir_z, dir_error_x, dir_error_y, dir_error_z
Ejemplo n.º 2
0
def generate_data_output(file_name, fibre, wl, ratio):
    """Function which runs over the EV branch of a RAT root file and applies
       the SMELLIE cut selection. Writes the number of hitd selection by 
       each cut to an output file and saves histograms for each cut region to 
       a root file. Can be used on MC simulations and SNO+ data.
     
     Args:
      file_name (string) : name of the input rat file
      fibre (string) : fibre label
      wl (string) : wavelength
      ratio (string) : string component to define which scattering length 
                       scaling factor the root file was produced with (in case of 
                       the simulation)
    """

    reader = ROOT.RAT.DU.DSReader(file_name, True)

    #get fibre specific variabes
    val = fibre_handling.FibreHandling(fibre)
    val.cut_values()

    sourcepos, sourcedir = val.get_fibre_position()
    AV1_cross, AV2_cross, PSUP_cross, n_scint, n_water = val.get_crossing_points(
        float(wl))

    #path lengths for direct beam
    scint_path = (AV2_cross - AV1_cross).Mag()
    water_path = (AV1_cross - sourcepos).Mag() + (PSUP_cross - AV2_cross).Mag()

    maxBeam, z_beam_min, z_beam_max, alpha_min, alpha_max, z_avout_min, z_avout_max, alpha_avin = val.spatialcuts[
        0], val.spatialcuts[1], val.spatialcuts[2], val.spatialcuts[
            3], val.spatialcuts[4], val.spatialcuts[5], val.spatialcuts[
                6], val.spatialcuts[7]

    tbeam, beam_tres, tAV1, t, tAV, tpsup, tmulti = val.timecuts[
        0], val.timecuts[1], val.timecuts[2], val.timecuts[3], val.timecuts[
            4], val.timecuts[5], val.timecuts[6]

    #define output root file
    outputroot = ROOT.TFile(
        "/data/langrock/rat-5.0-SMELLIE_analysis/" + str(fibre) + "/root/" +
        str(wl) + "_" + str(ratio) + "_data_water_c_mh.root", "recreate")

    #define output text file
    outputfile = open(
        "/data/langrock/rat-5.0-SMELLIE_analysis/" + str(fibre) + "/" +
        str(wl) + "_" + ratio + "_water.txt", "w")

    #get tools for data correction
    corrections = data_corrections.DataCorrections(reader)
    beam_center = corrections.fit_beam_time(sourcepos, sourcedir)
    pmtid = corrections.mh_corr()
    nevents = reader.GetEntryCount()

    #define histograms
    hist = define_histograms.DefineHistograms()

    #speed of light
    c = 300

    #variables used to count photons in cut region
    beam = 0
    double_refl = 0
    avin = 0
    avout = 0
    scatt = 0
    psup = 0
    multi = 0
    total = 0

    pmt_prop = rat.utility().GetPMTInfo()
    LightPath = rat.utility().GetLightPathCalculator()
    groupVelTime = rat.utility().GetGroupVelocity()

    #start looping through file
    for ievent in range(0, nevents):
        ds, run = reader.GetEntry(ievent), reader.GetRun()

        #loop through events
        for iev in range(ds.GetEVCount()):
            ev = ds.GetEV(iev)
            hist.h_nhits.Fill(ev.GetNhits())

            pmts = ev.GetCalPMTs()
            #run over pmts
            for ipmt in range(0, pmts.GetCount()):
                pmt_cal = pmts.GetPMT(ipmt)
                pmt_id = pmt_cal.GetID()

                #calculate multiple hits corrections
                P_occ = pmtid.GetBinContent(pmt_id) / nevents
                mu = 0
                if P_occ == 1:
                    mu = 0
                else:
                    mu = -math.log(1 - P_occ)
                c_mh = 1 + (mu - (1 - math.exp(-mu)))

                #get pmt position and direction with respect to fibre position
                pmtpos = pmt_prop.GetPosition(pmt_id)
                pmtdir = (pmtpos - sourcepos)

                #define spatial variables to cut on
                z = pmtpos.Z()
                theta = pmtpos.Theta()
                phi = pmtpos.Phi()
                alpha_mc_rad = math.acos(
                    (sourcedir * pmtdir) / (sourcedir.Mag() * pmtdir.Mag()))
                alpha_mc = math.degrees(alpha_mc_rad)

                pmt_time = pmt_cal.GetTime()

                #calculate time it takes the photon in respective pmt to get there
                LightPath.CalcByPosition(sourcepos, pmtpos)
                PathTime = groupVelTime.CalcByDistance(
                    LightPath.GetDistInScint(), LightPath.GetDistInAV(),
                    LightPath.GetDistInWater())

                time = pmt_time - PathTime

                #time for direct light to cross detector
                Beam_time = beam_center + (scint_path * n_scint +
                                           water_path * n_water) / c
                #AV1 reflection time off the outside of the AV
                AV_ref1_time = beam_center + (
                    (pmtpos - AV1_cross).Mag() +
                    (AV1_cross - sourcepos).Mag()) * n_water / c
                #AV2 reflection time off the inside of the AV after crossing the detector
                AV_ref2_time = beam_center + (
                    ((pmtpos - AV2_cross).Mag() +
                     (AV2_cross - sourcepos).Mag() - water_path) * n_scint +
                    water_path * n_water) / c
                #PSUP reflection time
                PSUP_ref_time = beam_center + (
                    ((pmtpos - PSUP_cross).Mag() + scint_path - water_path) *
                    n_scint + 2 * water_path * n_water) / c

                #count total number of hits detected and fill histograms, apply multiple hits correction
                total += 1 * c_mh
                hist.t_res.Fill(time - beam_center, c_mh)
                hist.angle_time.Fill(time - beam_center, alpha_mc)
                hist.z_time.Fill(time - beam_center, z)
                hist.theta_phi.Fill(phi, theta)
                hist.h_theta.Fill(theta, c_mh)
                hist.h_phi.Fill(phi, c_mh)

                ##### apply cuts, count photons and fill histograms for each each cut, including multiple hits correction ####

                #apply direct beam cuts
                if alpha_mc_rad <= (
                        maxBeam / 180.
                ) * math.pi and z < z_beam_max and z > z_beam_min and time < Beam_time + tbeam and (
                        pmt_time - PathTime - beam_center) <= beam_tres:
                    beam += 1 * c_mh

                    hist.t_res_beam.Fill(time - beam_center, c_mh)
                    hist.angle_time_beam.Fill(time - beam_center, alpha_mc)
                    hist.z_time_beam.Fill(time - beam_center, z)
                    hist.theta_phi_beam.Fill(phi, theta)
                    hist.h_theta_beam.Fill(theta, c_mh)
                    hist.h_phi_beam.Fill(phi, c_mh)

                #apply late pulse cuts
                elif alpha_mc_rad <= (
                        maxBeam / 180.
                ) * math.pi and z < z_beam_max and z > z_beam_min and time < Beam_time + tbeam and (
                        pmt_time - PathTime - beam_center) > beam_tres and (
                            pmt_time - PathTime - beam_center) < 50:
                    double_refl += 1 * c_mh

                    hist.t_res_double.Fill(time - beam_center, c_mh)
                    hist.angle_time_double.Fill(time - beam_center, alpha_mc)
                    hist.z_time_double.Fill(time - beam_center, z)
                    hist.theta_phi_double.Fill(phi, theta)
                    hist.h_theta_double.Fill(theta, c_mh)
                    hist.h_phi_double.Fill(phi, c_mh)

                else:
                    #apply cuts on outer (1st) AV reflections
                    if time < AV_ref1_time + tAV1 and alpha_mc_rad > (
                            alpha_min / 180.) * math.pi and alpha_mc_rad < (
                                alpha_max / 180.) * math.pi and (
                                    pmt_time - PathTime - beam_center
                                ) < t and z < z_avout_max and z > z_avout_min:
                        avout += 1 * c_mh

                        hist.t_res_avout.Fill(time - beam_center, c_mh)
                        hist.angle_time_avout.Fill(time - beam_center,
                                                   alpha_mc)
                        hist.z_time_avout.Fill(time - beam_center, z)
                        hist.theta_phi_avout.Fill(phi, theta)
                        hist.h_theta_avout.Fill(theta, c_mh)
                        hist.h_phi_avout.Fill(phi, c_mh)

                    #apply cuts on scattered events
                    elif time < AV_ref2_time - tAV:
                        scatt += 1 * c_mh

                        hist.t_res_scatt.Fill(time - beam_center, c_mh)
                        hist.angle_time_scatt.Fill(time - beam_center,
                                                   alpha_mc)
                        hist.z_time_scatt.Fill(time - beam_center, z)
                        hist.theta_phi_scatt.Fill(phi, theta)
                        hist.h_theta_scatt.Fill(theta, c_mh)
                        hist.h_phi_scatt.Fill(phi, c_mh)

                    #apply cuts on inner (2nd) AV reflections
                    elif time > AV_ref2_time - tAV and (
                        (time < PSUP_ref_time - tpsup and alpha_mc_rad >
                         (alpha_avin / 180.) * math.pi and alpha_mc_rad <
                         ((alpha_avin + 15) / 180.) * math.pi) or
                        (time < PSUP_ref_time - tpsup + 10 and alpha_mc_rad >
                         ((alpha_avin + 15) / 180.) * math.pi
                         and alpha_mc_rad <
                         ((alpha_avin + 20) / 180.) * math.pi) or
                        (time < PSUP_ref_time - tpsup + 20 and alpha_mc_rad >
                         ((alpha_avin + 20) / 180.) * math.pi
                         and alpha_mc_rad <
                         ((alpha_avin + 30) / 180.) * math.pi) or
                        (time < PSUP_ref_time - tpsup + 25 and alpha_mc_rad >
                         ((alpha_avin + 30) / 180.) * math.pi
                         and alpha_mc_rad <
                         ((alpha_avin + 40) / 180.) * math.pi) or
                        (time < PSUP_ref_time - tpsup + 35 and alpha_mc_rad >
                         ((alpha_avin + 40) / 180.) * math.pi
                         and alpha_mc_rad <
                         ((alpha_avin + 50) / 180.) * math.pi) or
                        (time < PSUP_ref_time - tpsup + 40 and alpha_mc_rad >
                         ((alpha_avin + 50) / 180.) * math.pi
                         and alpha_mc_rad <
                         ((alpha_avin + 60) / 180.) * math.pi) or
                        (time < PSUP_ref_time - tpsup + 45 and alpha_mc_rad >
                         ((alpha_avin + 60) / 180.) * math.pi)):
                        avin += 1 * c_mh

                        hist.t_res_avin.Fill(time - beam_center, c_mh)
                        hist.angle_time_avin.Fill(time - beam_center, alpha_mc)
                        hist.z_time_avin.Fill(time - beam_center, z)
                        hist.theta_phi_avin.Fill(phi, theta)
                        hist.h_theta_avin.Fill(theta, c_mh)
                        hist.h_phi_avin.Fill(phi, c_mh)

                    #apply cuts on PSUP reflections
                    elif time > AV_ref2_time - tAV and time < PSUP_ref_time + tmulti:
                        psup += 1 * c_mh

                        hist.t_res_psup.Fill(time - beam_center, c_mh)
                        hist.angle_time_psup.Fill(time - beam_center, alpha_mc)
                        hist.z_time_psup.Fill(time - beam_center, z)
                        hist.theta_phi_psup.Fill(phi, theta)
                        hist.h_theta_psup.Fill(theta, c_mh)
                        hist.h_phi_psup.Fill(phi, c_mh)

                    #apply cuts on multiple effects
                    elif time > PSUP_ref_time + tmulti:
                        multi += 1 * c_mh

                        hist.t_res_multi.Fill(time - beam_center, c_mh)
                        hist.angle_time_multi.Fill(time - beam_center,
                                                   alpha_mc)
                        hist.z_time_multi.Fill(time - beam_center, z)
                        hist.theta_phi_multi.Fill(phi, theta)
                        hist.h_theta_multi.Fill(theta, c_mh)
                        hist.h_phi_multi.Fill(phi, c_mh)

    #save histograms to root file
    outputroot.Write()
    outputroot.Close()

    #calculate poissonian uncertainty on all cut region counts
    total_error = math.sqrt(float(total))
    scatt_error = math.sqrt(float(scatt))
    beam_error = math.sqrt(float(beam))
    double_refl_error = math.sqrt(float(double_refl))
    avin_error = math.sqrt(float(avin))
    avout_error = math.sqrt(float(avout))
    psup_error = math.sqrt(float(psup))
    multi_error = math.sqrt(float(multi))

    #calculate the ratio of scattered/in-beam events to the total number of events and the uncertainty on the ratio
    ratio_scatt = float(scatt) / float(total)
    ratio_scatt_error = math.sqrt(
        math.pow(scatt_error / float(total), 2) +
        math.pow(float(scatt) * total_error / math.pow(float(total), 2), 2))
    ratio_beam = float(beam) / float(total)
    ratio_beam_error = math.sqrt(
        math.pow(beam_error / float(total), 2) +
        math.pow(float(beam) * total_error / math.pow(float(total), 2), 2))

    #save all values to a txt file
    outputfile.write(wl)
    outputfile.write('\t')
    outputfile.write(ratio.replace('p', '.'))
    outputfile.write('\t scattering ratio: ')
    outputfile.write(str(ratio_scatt))
    outputfile.write('\t +/- ')
    outputfile.write(str(ratio_scatt_error))
    outputfile.write('\t beam ratio: ')
    outputfile.write(str(ratio_beam))
    outputfile.write('\t +/- ')
    outputfile.write(str(ratio_beam_error))
    outputfile.write('\n \n \n \n')

    outputfile.write("total: " + str(total) + " +/-" + str(total_error) + "\n")
    outputfile.write("beam: " + str(beam) + " +/-" + str(beam_error) + "\n")
    outputfile.write("double_refl: " + str(double_refl) + " +/-" +
                     str(double_refl_error) + "\n")
    outputfile.write("avin: " + str(avin) + " +/-" + str(avin_error) + "\n")
    outputfile.write("avout: " + str(avout) + " +/-" + str(avout_error) + "\n")
    outputfile.write("scatt: " + str(scatt) + " +/-" + str(scatt_error) + "\n")
    outputfile.write("psup: " + str(psup) + " +/-" + str(psup_error) + "\n")
    outputfile.write("multi: " + str(multi) + " +/-" + str(multi_error) + "\n")

    outputfile.close()
Ejemplo n.º 3
0
def find_noise(file_name, fibre, wl, ratio):
    """Function which runs over the MC branch of a RAT root file and applies
       the SMELLIE cut selection to all photons which originate from PMT noise. 
       Writes the number of photons selected by each cut to an output file and 
       saves histograms for each cut region to a root file. Can only be used on 
       MC simulations.
     
     Args:
      file_name (string) : name of the input rat file
      fibre (string) : fibre label
      wl (string) : wavelength
      ratio (string) : string component to define which scattering length 
                       scaling factor the root file was produced with
    """

    reader = ROOT.RAT.DU.DSReader(file_name,True)   

    #get fibre specific variables
    val = fibre_handling.FibreHandling(fibre)
    val.cut_values()

    sourcepos, sourcedir = val.get_fibre_position()
    AV1_cross, AV2_cross, PSUP_cross, n_scint, n_water = val.get_crossing_points(float(wl)) 

    #path lengths for direct beam
    scint_path = (AV2_cross - AV1_cross).Mag()
    water_path = (AV1_cross - sourcepos).Mag() + (PSUP_cross - AV2_cross).Mag()

    #get cut values
    maxBeam, z_beam_min, z_beam_max, alpha_min, alpha_max, z_avout_min, z_avout_max, alpha_avin = val.spatialcuts[0], val.spatialcuts[1], val.spatialcuts[2], val.spatialcuts[3], val.spatialcuts[4], val.spatialcuts[5], val.spatialcuts[6], val.spatialcuts[7]

    tbeam, beam_tres, tAV1, t, tAV, tpsup, tmulti = val.timecuts[0], val.timecuts[1], val.timecuts[2], val.timecuts[3], val.timecuts[4], val.timecuts[5], val.timecuts[6]

    #define output root file
    outputroot = ROOT.TFile("/data/langrock/rat-5.0-SMELLIE_analysis/" + str(fibre) + "/root/" + str(wl) + "_" + ratio + "_noise.root","recreate")

    #define output text file
    outputfile = open("/data/langrock/rat-5.0-SMELLIE_analysis/" + str(fibre) + "/" + str(wl) + "_" + ratio + "_noise.txt","w")

    #define histograms
    hist = define_histograms.DefineHistograms()

    #speed of light
    c = 300

    #variables used to count photons in cut region
    beam = 0
    avin = 0
    avout = 0
    scatt = 0 
    psup = 0
    multi = 0
    total = 0
    double_refl = 0

    pmt_prop = rat.utility().GetPMTInfo()  
    LightPath = rat.utility().GetLightPathCalculator()
    groupVelTime = rat.utility().GetGroupVelocity()

    #start looping through file
    for ievent in range(0,reader.GetEntryCount()):
        ds, run = reader.GetEntry(ievent), reader.GetRun()
        mc = ds.GetMC()
    
        #run over pmts
        for ipmt in range(mc.GetMCPMTCount()): 
            pmt_id = mc.GetMCPMT(ipmt).GetID()
            #get pmt position and direction with respect to fibre position
            pmtpos = pmt_prop.GetPosition(pmt_id)
            pmtdir = (pmtpos - sourcepos)

            #define spatial variables to cut on
            z = pmtpos.Z()
            theta = pmtpos.Theta()
            phi = pmtpos.Phi()
            alpha_mc_rad = math.acos((sourcedir * pmtdir)/(sourcedir.Mag() * pmtdir.Mag()))
            alpha_mc = math.degrees(alpha_mc_rad)        

            #calculate time it takes the photon in respective pmt to get there
            LightPath.CalcByPosition(sourcepos,pmtpos) 
            PathTime = groupVelTime.CalcByDistance(LightPath.GetDistInScint(),LightPath.GetDistInAV(),LightPath.GetDistInWater())

            #time for direct light to cross detector
            Beam_time = (scint_path*n_scint + water_path*n_water)/c
	    #AV1 reflection time off the outside of the AV
            AV_ref1_time = ((pmtpos - AV1_cross).Mag() + (AV1_cross - sourcepos).Mag()) * n_water /c        
            #AV2 reflection time off the inside of the AV after crossing the detector
            AV_ref2_time = (((pmtpos - AV2_cross).Mag() + (AV2_cross - sourcepos).Mag() - water_path)*n_scint + water_path*n_water) /c 
            #PSUP reflection time
            PSUP_ref_time = (((pmtpos - PSUP_cross).Mag() + scint_path - water_path)*n_scint + 2*water_path*n_water) /c

            #loop through photons in PMT
            mc_pmt = mc.GetMCPMT(ipmt)
            for photon in range(mc_pmt.GetMCPECount()):
                mc_photon = mc_pmt.GetMCPE(photon)
                pmt_time = mc_photon.GetCreationTime()
                time = pmt_time - PathTime

                #if photon is a noise hit, apply cuts, count photons and fill histograms for each each cut
                if mc_photon.GetNoise():

                    #count total number of photons detected and fill histograms
                    total += 1                    
                    hist.t_res.Fill(time)
                    hist.angle_time.Fill(time,alpha_mc)
                    hist.z_time.Fill(time,z)
                    hist.theta_phi.Fill(phi,theta)
                    hist.h_theta.Fill(theta)
                    hist.h_phi.Fill(phi)

                    #apply direct beam cuts
                    if alpha_mc_rad<=(maxBeam/180.)*math.pi and z < z_beam_max and z > z_beam_min and time < Beam_time+tbeam and (pmt_time - PathTime) < beam_tres:
                        beam += 1
                    
                        hist.t_res_beam.Fill(time)
                        hist.angle_time_beam.Fill(time,alpha_mc)
                        hist.z_time_beam.Fill(time,z)    
                        hist.theta_phi_beam.Fill(phi,theta)
                        hist.h_theta_beam.Fill(theta)
                        hist.h_phi_beam.Fill(phi)

                    #apply late pulse cuts
                    elif alpha_mc_rad<=(maxBeam/180.)*math.pi and z < z_beam_max and z > z_beam_min and time < Beam_time+tbeam and (pmt_time - PathTime) > beam_tres and (pmt_time - PathTime) < 50:
                        double_refl += 1
                    
                        hist.t_res_double.Fill(time)
                        hist.angle_time_double.Fill(time,alpha_mc)
                        hist.z_time_double.Fill(time,z)    
                        hist.theta_phi_double.Fill(phi,theta)
                        hist.h_theta_double.Fill(theta)
                        hist.h_phi_double.Fill(phi)

                    else:
                        #apply cuts on outer (1st) AV reflections
                        if time < AV_ref1_time+tAV1 and alpha_mc_rad > (alpha_min/180.)*math.pi and alpha_mc_rad < (alpha_max/180.)*math.pi and (pmt_time -  PathTime) < t and z < z_avout_max and z > z_avout_min: 
                            avout += 1

                            hist.t_res_avout.Fill(time)
                            hist.angle_time_avout.Fill(time,alpha_mc)
                            hist.z_time_avout.Fill(time,z)
                            hist.theta_phi_avout.Fill(phi,theta)
                            hist.h_theta_avout.Fill(theta)
                            hist.h_phi_avout.Fill(phi)

                        #apply cuts on scattered events
                        elif time < AV_ref2_time-tAV:
                            scatt += 1
                            
                            hist.t_res_scatt.Fill(time)
                            hist.angle_time_scatt.Fill(time,alpha_mc)
                            hist.z_time_scatt.Fill(time,z)
                            hist.theta_phi_scatt.Fill(phi,theta)
                            hist.h_theta_scatt.Fill(theta)
                            hist.h_phi_scatt.Fill(phi)
                            
                        #apply cuts on inner (2nd) AV reflections
                        elif time > AV_ref2_time-tAV and ((time < PSUP_ref_time-tpsup and alpha_mc_rad > (alpha_avin/180.)*math.pi and alpha_mc_rad < ((alpha_avin+15)/180.)*math.pi) or (time < PSUP_ref_time-tpsup+10 and alpha_mc_rad > ((alpha_avin+15)/180.)*math.pi and alpha_mc_rad < ((alpha_avin+20)/180.)*math.pi) or (time < PSUP_ref_time-tpsup+20 and alpha_mc_rad > ((alpha_avin+20)/180.)*math.pi and alpha_mc_rad < ((alpha_avin+30)/180.)*math.pi) or (time < PSUP_ref_time-tpsup+25 and alpha_mc_rad > ((alpha_avin+30)/180.)*math.pi and alpha_mc_rad < ((alpha_avin+40)/180.)*math.pi) or (time < PSUP_ref_time-tpsup+35 and alpha_mc_rad > ((alpha_avin+40)/180.)*math.pi and alpha_mc_rad < ((alpha_avin+50)/180.)*math.pi) or (time < PSUP_ref_time-tpsup+40 and alpha_mc_rad > ((alpha_avin+50)/180.)*math.pi and alpha_mc_rad < ((alpha_avin+60)/180.)*math.pi) or (time < PSUP_ref_time-tpsup+45 and alpha_mc_rad > ((alpha_avin+60)/180.)*math.pi)):
                            avin += 1
                        
                            hist.t_res_avin.Fill(time)
                            hist.angle_time_avin.Fill(time,alpha_mc)
                            hist.z_time_avin.Fill(time,z)
                            hist.theta_phi_avin.Fill(phi,theta)
                            hist.h_theta_avin.Fill(theta)
                            hist.h_phi_avin.Fill(phi)

                        #apply cuts on PSUP reflections
                        elif time >  AV_ref2_time-tAV and time < PSUP_ref_time+tmulti: 
                            psup += 1

                            hist.t_res_psup.Fill(time)
                            hist.angle_time_psup.Fill(time,alpha_mc)
                            hist.z_time_psup.Fill(time,z)
                            hist.theta_phi_psup.Fill(phi,theta)
                            hist.h_theta_psup.Fill(theta)
                            hist.h_phi_psup.Fill(phi)

                        #apply cuts on multiple effects
                        elif time > PSUP_ref_time+tmulti:
                            multi += 1

                            hist.t_res_multi.Fill(time)
                            hist.angle_time_multi.Fill(time,alpha_mc)
                            hist.z_time_multi.Fill(time,z)
                            hist.theta_phi_multi.Fill(phi,theta)
                            hist.h_theta_multi.Fill(theta)
                            hist.h_phi_multi.Fill(phi)

    #save histograms to root file
    outputroot.Write()
    outputroot.Close()

    #save all values to a text file
    outputfile.write("total: " + str(total) + "\n")
    outputfile.write("beam: " + str(beam) + "\n")
    outputfile.write("double_refl: " + str(double_refl) + "\n")
    outputfile.write("avin: " + str(avin) + "\n")
    outputfile.write("avout: " + str(avout) + "\n")
    outputfile.write("scatt: " + str(scatt) + "\n")
    outputfile.write("psup: " + str(psup) + "\n")
    outputfile.write("multi: " + str(multi) + "\n")

    outputfile.close()
Ejemplo n.º 4
0
def get_water_profiles(file_name, fibre, n):
    """Function which runs over the EV branch of a RAT root file to extract the angular
       beam profile. It fills angular histograms with variable bin width determined by the 
       number of PMTs n covered by the angular bin. The histogram to be extracted from air-fill
       data are converted to a water-fill profile for analysis purposes.
     
     Args:
      file_name (string) : name of the input rat file
      fibre (string) : fibre label
      n (int) : number of PMTs to be covered by each angular bin

     Returns:
      a histogram normalised by the number of working PMTs per bin
    """

    reader = ROOT.RAT.DU.DSReader(file_name, False)

    #get fibre specific variables
    val = fibre_handling.FibreHandling(fibre)
    sourcepos, sourcedir = val.get_fibre_position()

    pmt_prop = rat.utility().GetPMTInfo()

    #get bins of the angular histogram to be filled dependent on the number of PMTs n to be covered by each bin
    angle = angle_measurement.AngleMeasurement()
    angle.get_number_of_pmts(n)
    angle.create_pmt_angle_map(sourcepos, sourcedir)
    angle.get_bin_edges()

    #get tools for data correction
    corrections = data_corrections.DataCorrections(reader)
    pmtid = corrections.mh_corr()
    nevents = reader.GetEntryCount()

    #define angular histograms
    h_angle = ROOT.TH1D("h_angle", "", angle.nbins, angle.bin_edges)
    h_angle_pmt = ROOT.TH2D("h_angle_pmt", "", 1000, 0, 10000, angle.nbins,
                            angle.bin_edges)

    #start looping through file
    for ievent in range(0, nevents):
        ds = reader.GetEntry(ievent)

        #loop through events
        for iev in range(ds.GetEVCount()):
            ev = ds.GetEV(iev)

            #run over PMTs
            pmts = ev.GetCalPMTs()
            for ipmt in range(0, pmts.GetCount()):
                pmt_cal = pmts.GetPMT(ipmt)
                pmt_id = pmt_cal.GetID()

                #calculate multiple hits corrections
                P_occ = pmtid.GetBinContent(pmt_id) / nevents
                mu = 0
                if P_occ == 1:
                    mu = 0
                else:
                    mu = -math.log(1 - P_occ)
                c_mh = 1 + (mu - (1 - math.exp(-mu)))

                #get pmt position and direction with respect to fibre position
                pmtpos = pmt_prop.GetPosition(pmt_id)
                pmtdir = (pmtpos - sourcepos)

                #calculate angle with respect to the fibre direction
                alpha_mc_rad = math.acos(
                    (sourcedir * pmtdir) / (sourcedir.Mag() * pmtdir.Mag()))
                alpha_mc = math.degrees(alpha_mc_rad)

                #refractive indices of all involved materials
                n_quartz = 1.46
                n_air = 1.0003
                n_water = 1.34

                #snell's law - calculate incident angle alpha_quartz from air-fill angle and then use alpha_quartz to calculate the water-fill angle alpha_water
                alpha_quartz = math.asin(
                    math.sin(alpha_mc_rad) * n_air / n_quartz)
                alpha_water = math.degrees(
                    math.asin(math.sin(alpha_quartz) * n_quartz / n_water))

                #fill histograms
                h_angle.Fill(alpha_water, c_mh)
                h_angle_pmt.Fill(pmt_id, alpha_water)

    #normalise angular histogram by number of working PMTs per bin and return
    return angle.normalise_bins(h_angle_pmt, h_angle)