Example #1
0
def generatePulses(frame):
    # this dom is the one which should launch while its only LC partner (dom 2) is
    # dead from previous launches
    dom1 = OMKey(47, 1)
    # this dom will be hit at all three times, first to ensure that both digitizers
    # are busy and then to supply the LC high to dom1
    dom2 = OMKey(47, 2)
    # this dom will be pulse twice (time1 and time 2) to ensure that dom2 has LC and
    # makes HLC readouts (to maximize deadtime)
    dom3 = OMKey(47, 3)

    #This is a IT DOM to test IT SLC
    dom4 = OMKey(47, 62)

    pulseWeight = 1000

    time1 = 0
    time2 = time1 + 6600
    time3 = time2 + 8000

    pulses = simclasses.I3MCPulseSeriesMap()
    series1 = simclasses.I3MCPulseSeries()
    series2 = simclasses.I3MCPulseSeries()
    series3 = simclasses.I3MCPulseSeries()

    pulse = simclasses.I3MCPulse()
    pulse.charge = pulseWeight
    pulse.time = time1
    series3.append(pulse)
    series2.append(pulse)

    pulse.time = time2
    series3.append(pulse)
    series2.append(pulse)

    pulse.time = time3
    series2.append(pulse)
    series1.append(pulse)

    pulses[dom1] = series1
    pulses[dom2] = series2
    pulses[dom3] = series3

    pulse.charge = 5000
    pulse.time = 500000
    series2.append(pulse)
    pulses[dom4] = series2

    frame.Put("TestPulses", pulses)
    def _GetDroppedDoms(self):
        """
        Returns a list of dropped doms. Only experimental data supported (run id required)

        Returns:
            list: A list of `OMKeys`.
        """

        # Simulation is not supported
        if self.simulation:
            icetray.logging.log_fatal("Dropped dom information is not supported for simulation.")

        self._GetDomInfoFromI3Live()

        droppedDoms = []

        # Dropped doms are categorized by souce, e.g. `user_alert` and `moni_file`
        for key, src in self.runInfo['dropped_doms'].items():
            for om in src:
                # Only use this dropped dom if it dropped before the good stop time
                # string compare works since both date times are in the correct format for it
                if om['drop_time'] < self.snapshot['runs'][0]['good_tstop']:
                    droppedDoms.append(OMKey(om['dom_string'], om['dom_position']))

        return droppedDoms
    def _GetUnconfiguredDoms(self):
        """
        Returns the list of unconfigured doms.

        If the simulation flag is set to `True`, it checks the dom status in the frame.
        If a dom is not in the status or has no HV, it is considered as unconfigured dom.

        If you provided a run id and the simulation flag is `False`, it gets the information from I3Live.

        Returns:
            list: A list if `OMKeys`.
        """

        unconfDoms = []
        icetray.logging.log_info("Getting unconfigured OMs")
        # If simulation is True, we need to get the information from the GCD file
        if self.simulation:
            for dom in self.frame['I3Geometry'].omgeo.keys():
                if self.ignoreNewDOMs  and \
                   self.frame['I3Geometry'].omgeo[dom].omtype in self.newDOMTypes : 
                    continue
                if dom not in self.frame['I3DetectorStatus'].dom_status.keys() or \
                   self.frame['I3DetectorStatus'].dom_status[dom].pmt_hv == 0:
                    unconfDoms.append(dom)
        else:
            self._GetDomInfoFromI3Live()
            
            for key, om in self.runInfo['unconfigured_doms'].items():
                unconfDoms.append(OMKey(om['string'], om['position']))
        icetray.logging.log_info("Finished getting unconfigured OMs")
        return unconfDoms
    def _GetNoHVDoms(self):
        """
        Returns the list of doms with no HV.

        If the simulation flag is set to `True`, it checks the dom status in the frame.

        If you provided a run id and the simulation flag is `False`, it gets the information from I3Live.

        Returns:
            list: A list if `OMKeys`.
        """

        noHVDoms = []

        # If simulation is True, we need to get the information from the GCD file
        if self.simulation:
            for dom in self.frame['I3Geometry'].omgeo.keys():
                if self.ignoreNewDOMs and \
                   self.frame['I3Geometry'].omgeo[dom].omtype in self.newDOMTypes : 
                    continue
                if self.frame['I3DetectorStatus'].dom_status[dom].pmt_hv == 0:
                    noHVDoms.append(dom)
        else:
            self._GetDomInfoFromI3Live()
            
            if 'No HV' in self.runInfo['problem_doms'].keys():
                for key, om in self.runInfo['problem_doms']['No HV'].items():
                    noHVDoms.append(OMKey(om['string'], om['position']))

        return noHVDoms
Example #5
0
def generateOMString(stringNumber, startPos, numDoms, spacing, direction):
    orientation = dataclasses.I3Orientation(
        0, 0, -1, 1, 0, 0)  # same orientation as icecube DOMs (dir=down)
    area = 0.5857538 * I3Units.meter2  # same area as KM3NET MDOMs
    geomap = dataclasses.I3OMGeoMap()
    x = startPos.x
    y = startPos.y
    z = startPos.z
    dx = [spacingVal * direction.x for spacingVal in spacing]
    dy = [spacingVal * direction.y for spacingVal in spacing]
    dz = [spacingVal * direction.z for spacingVal in spacing]

    # create OMKeys and I3OMGeo for DOMs on string and add them to the map
    for i in xrange(0, numDoms):
        omkey = OMKey(stringNumber, i, 0)
        omGeometry = dataclasses.I3OMGeo()
        omGeometry.omtype = dataclasses.I3OMGeo.OMType.IceCube
        omGeometry.orientation = orientation
        omGeometry.area = area
        omGeometry.position = dataclasses.I3Position(x + dx[i] * i,
                                                     y + dy[i] * i,
                                                     z + dz[i] * i)
        geomap[omkey] = omGeometry

    return geomap
def convertToOmkeyList(stringList, layers):
    omkeyList = []
    for string in stringList:
        for dom in layers:
            omkeyList.append(OMKey(string, dom, 0))

    return omkeyList
Example #7
0
def generatePulses(frame):
    global n
    dom1 = OMKey(47,1)
    dom2 = OMKey(47,2)
    dom3 = OMKey(47,15)
    
    dom4 = OMKey(47,25)
    dom5 = OMKey(47,26)
  
    pulseWeight = 10
    pulses = simclasses.I3MCPulseSeriesMap()
    series = simclasses.I3MCPulseSeries()
    
    pulse = simclasses.I3MCPulse()
    pulse.charge = pulseWeight
  
    if(n==1):
        time1 = 0
        time2 = 29*icetray.I3Units.microsecond
        
        
    else:
        time1 = 2*29*icetray.I3Units.microsecond
        time2 = 3*29*icetray.I3Units.microsecond
        series2 = simclasses.I3MCPulseSeries()        
        series3 = simclasses.I3MCPulseSeries()
        
    pulse.time = time1
    series.append(pulse)
    pulse.time = time2
    series.append(pulse)
    
    pulses[dom1]=series
    pulses[dom2]=series
    pulses[dom3]=series

    if(n == 1):
        pulses[dom4]=series
    else:
        pulse.time = 29*icetray.I3Units.microsecond+200
        series = simclasses.I3MCPulseSeries()
        series.append(pulse)
        pulses[dom5]=series
        
        
    frame.Put("TestPulses",pulses)
Example #8
0
def fillDT(frame, Streams2=[icetray.I3Frame.DAQ]):
    if 'ATWDPortiaPulse' not in frame:
        print 'no pulse'
        return False

    # Get ATWD info
    calib_atwd = frame['CalibratedATWD']
    cleanData = frame['CleanInIceRawData']
    #print cleanData
    # Loop over OM Keys and get calibrated ATWD
    # Set SC pulses
    SC_DOMs = [OMKey(55, d) for d in SCDoms]
    for key, domlaunchs in cleanData:
        for i in range(len(SCDoms)):

            if key == SC_DOMs[i]:
                domTime = 9999999
                passLC = False
                for launch in domlaunchs:
                    if launch.time < domTime:
                        domTime = launch.time
                        passLC = launch.lc_bit

                # Do not look at events where LCBit fail
                if not passLC: continue
                if domTime < 0: continue

                # Now we have start time, loop over calibrated
                # waveforms and keep the waveform that has shortest
                # time
                waveForms = calib_atwd.get(key)
                dT = -999
                maxV = -999
                for waveform in waveForms:
                    if waveform.time <= domTime:
                        # This is it, record info
                        voltages = waveform.waveform
                        binSize = waveform.binWidth
                        for j in range(len(voltages)):
                            Voltage = voltages[j] / I3Units.V
                            if maxV < Voltage:
                                maxV = Voltage
                                dT = (
                                    (len(voltages) - j) * binSize) / I3Units.ns
                        break

                # Now save the wavetime, if non-negative
                if dT < 0: continue

                # Fill
                h_dT_perDom[i].Fill(dT)

            # end if have right DOM
        # end for loop over SC DOMS
    # end loop over clean data
    return True
def generateMCPEList(photons, modkey):
    omkey = OMKey(modkey.string, modkey.om, 0)
    mcpeList = simclasses.I3MCPESeries()
    photonList = []
    for photon in photons:
        if survived(photon,omkey):
            mcpe = simclasses.I3MCPE()
            #mcpe.id = dataclasses.I3ParticleID(photon.particleMajorID, photon.particleMinorID)
            mcpe.npe = 1
            mcpe.time = photon.time #TODO: change to corrected time
            mcpeList.append(mcpe)
            photonList.append(photon)
    
    return mcpeList, photonList
Example #10
0
def getPhotonDataFromFrames(frameList):
    photonAngle = []
    photonWavelength = []

    for frame in frameList:
        photonMap = frame["I3Photons"]
        for modkey, photons in photonMap:
            for photon in photons:
                photonAngle.append(
                    getrelativeAngle(photon, OMKey(modkey.string, modkey.om,
                                                   0)))
                photonWavelength.append(photon.wavelength)

    return photonAngle, photonWavelength
    def test_I3FlasherInfo_equality(self):

        fi1 = dataclasses.I3FlasherInfo()
        fi2 = dataclasses.I3FlasherInfo()

        fi1.flashing_om = OMKey(2, 1, 0)
        fi2.flashing_om = OMKey(2, 1, 0)
        fi1.flash_time = 1.0
        fi2.flash_time = 1.0
        fi1.atwd_bin_size = 1.0
        fi2.atwd_bin_size = 1.0
        fi1.led_brightness = 1
        fi2.led_brightness = 1
        fi1.mask = 1
        fi2.mask = 1
        fi1.width = 1
        fi2.width = 1
        fi1.rate = 1
        fi2.rate = 1
        fi1.raw_atwd3 = [1, 2, 3]
        fi2.raw_atwd3 = [1, 2, 3]

        self.assertTrue(fi1 == fi2, "this should be true.")
Example #12
0
    def Physics(self, frame):
        fit, mask, fit_status = get_fit(frame, 0.5)

        mask1 = dataclasses.I3RecoPulseSeriesMapMask(frame, 'All_pulses')
        count = 0

        for omkey in frame['WaveformInfo'].keys():
            dom = int(omkey.split(',')[1])
            string = int(omkey.split(',')[0].split('(')[1])
            key = OMKey(string, dom)
            mask1.set(key, bool(mask[count]))
            count += 1

        frame['NewMask'] = mask1

        self.PushFrame(frame)
    def _GetTemporarilyBadDoms(self):
        """
        Returns a list of temporarily bad doms. Only experimental data supported (run id required)

        Returns:
            list: A list of `OMKeys`.
        """

        # Simulation is not supported
        if self.simulation:
            icetray.logging.log_fatal("Temporarily bad dom information is not supported for simulation.")

        self._GetDomInfoFromI3Live()

        tmpBadDoms = []
       
        if 'Temporarily bad' in self.runInfo['problem_doms'].keys(): 
            for key, om in self.runInfo['problem_doms']['Temporarily bad'].items():
                tmpBadDoms.append(OMKey(om['string'], om['position']))

        return tmpBadDoms
    def _GetDarkNoiseModeDoms(self):
        """
        Returns a list of good dark noise doms. That means, doms that have HV, are configured, and are in dark noise mode.

        If the simulation flag is set to `True`, it checks the dom status in the frame.

        If you provided a run id and the simulation flag is `False`, it gets the information from I3Live.

        Note: Currently is the only source the frame. Will be updated as soon I3Live provides this information.

        Returns:
            list: A list of `OMKeys`.
        """

        goodDarkNoiseDoms = []

        # If simulation is True, we need to get the information from the GCD file
        if self.simulation:
            for dom in self.frame['I3Geometry'].omgeo.keys():
                if self.ignoreNewDOMs and \
                   self.frame['I3Geometry'].omgeo[dom].omtype in self.newDOMTypes : 
                    continue
                if dom in self.frame['I3DetectorStatus'].dom_status.keys() and \
                   self.frame['I3DetectorStatus'].dom_status[dom].lc_mode == self.frame['I3DetectorStatus'].dom_status[dom].LCMode.SoftLC and \
                   self.frame['I3DetectorStatus'].dom_status[dom].pmt_hv > 0:
                    goodDarkNoiseDoms.append(dom)
        else:
            self._GetDomInfoFromI3Live()
            
            if 'No LC' in self.runInfo['problem_doms'].keys():
                for key, om in self.runInfo['problem_doms']['No LC'].items():
                    position = "%s-%s" % (om['string'], om['position'])

                    if position in self.runInfo['configured_doms'].keys() and \
                       position not in self.runInfo['problem_doms']['No HV'].keys():
                        goodDarkNoiseDoms.append(OMKey(om['string'], om['position']))

        return goodDarkNoiseDoms
Example #15
0
def harvest_calibrated_waveforms(inputfile,
                                 outputfile,
                                 digitizer,
                                 targets=None,
                                 debug=False):
    '''
    Inputs
    --------
    inputfile: str (name of an i3 file)

    outputfile: str (name of a vzp file)

    digitizer: str (type of digitization to use: ATWD or FADC)

    targets: str (name of a .py file containing a list of Tuples called target)

    debug: bool (debug flag)
    '''
    print("harvesting ", inputfile, "...")
    import numpy as np
    from icecube.icetray import OMKey, I3Units
    from icecube import dataclasses, simclasses
    from icecube import dataio
    import pickle

    if debug:
        import matplotlib.pyplot as plt

    exec("from utils.%s import targets" %
         (args.targets.split('.')[-2].split('/')[-1]))
    #convert tuples into OMKey objects
    targets_key = []
    for e in targets:
        a = OMKey(e[0], e[1])
        targets_key.append(a)

    targets = targets_key

    F = dataio.I3File(inputfile)
    n_hits_total = 0.
    n_hits_hlc = 0.
    previous_atwd_1_hit = {}
    previous_hit = {}
    waveforms = {}
    for om in targets:

        waveforms[om] = {}
        waveforms[om]['traces'] = []
        waveforms[om]['times'] = []
        waveforms[om]['type'] = digitizer
        waveforms[om]['n_HLC'] = 0.0
        waveforms[om]['n_tot'] = 0.0
        waveforms[om]['deadtime'] = []
        previous_atwd_1_hit[om] = 0.0
        previous_hit[om] = None

    n_frames = 0
    while F.more():

        frame = F.pop_frame()

        for hits in frame['CalibratedWaveforms']:
            pmt = hits[0]
            if pmt in targets:
                for h in hits[1]:
                    if h.hlc:
                        waveforms[pmt]['n_HLC'] += 1.

                        if str(h.source) == digitizer:
                            #
                            # Store the waveform information
                            # Note: waveforms at this stage give positive pulses
                            #
                            waveforms[pmt]['traces'].append(h.waveform)
                            waveforms[pmt]['times'].append(h.time)
                            if debug:
                                plt.plot(np.array(h.waveform) / I3Units.mV)
                                plt.xlabel('sample #')
                                plt.ylabel('Waveform signal (mV)')
                                plt.show()

                        # Deadtime calculations
                        #-----------------------------------------------------------------------
                        # Deal with the deadtime between ATWD recordings
                        # And overflow to higher amplification channels
                        #
                        # No matter the type of digitizer data wanted, both channels
                        # (ATWD and FADC) need to distinguish which ATWD fired on a hit
                        # before computing the associated deadtime

                        if digitizer == 'ATWD':
                            if str(
                                    h.source
                            ) == 'ATWD' and h.channel == 0:  # Deal with the deadtime between ATWD recordings
                                # And overflow to higher amplification channels
                                # ATWD A
                                if h.source_index == 0:
                                    previous_atwd_1_hit[pmt] = h.time
                                    waveforms[pmt]['deadtime'].append(6023.)

                                elif h.source_index == 1:

                                    if previous_atwd_1_hit[pmt] is None:
                                        print "at file ", inputfile, " frame # ", n_frames
                                        sys.exit(
                                            "ERROR: something is fishy: you found an atwd_b hit with no previous atwd_a hit."
                                        )

                                    tprevious = previous_atwd_1_hit[
                                        pmt] + 32500  # time for ATWD A to finish digitizing
                                    dead_b = h.time + 427  # start of the ATWD B deadtime
                                    waveforms[pmt]['deadtime'].append(
                                        tprevious - dead_b)
                                    previous_atwd_1_hit[pmt] = None

                        elif digitizer == 'FADC' and str(h.source) == 'FADC':

                            if previous_hit[pmt] is None:
                                print "at file ", inputfile, " frame # ", n_frames
                                sys.exit(
                                    "ERROR: something is fishy: First hit found was an FADC hit..."
                                )

                            elif str(previous_hit[pmt].source
                                     ) == 'ATWD' and previous_hit[
                                         pmt].source_index == 0:  #if ATWD A:
                                previous_atwd_1_hit[pmt] = h.time
                                waveforms[pmt]['deadtime'].append(
                                    50
                                )  # only a 50ns delay before ATWD-b can kick in

                            elif str(previous_hit[pmt].source
                                     ) == 'ATWD' and previous_hit[
                                         pmt].source_index == 1:  #if ATWD B

                                tprevious = previous_atwd_1_hit[pmt] + 32500
                                waveforms[pmt]['deadtime'].append(tprevious -
                                                                  (h.time +
                                                                   6400))

                        previous_hit[pmt] = h

                    else:
                        print "HEY! found an SLC hit!!!"

                    waveforms[pmt]['n_tot'] += 1.

        n_frames += 1

    pickle.dump([n_frames, waveforms], open(outputfile, "wb"))
    return
Example #16
0
    def Physics(self, frame):
        print(self.run_id, self.evt_id)

        wfs = frame[self.key]
        if self.string is None and self.dom is None:
            prev_string = 1
            wf_cnt = 0
            fig, ax = plt.subplots()
            for omkey in wfs.keys():
                if omkey.string != prev_string:
                    prev_string = omkey.string
                    if wf_cnt > 0:
                        ax.legend(loc='best')
                        ax.set_xlabel(r'Time / ns')
                        ax.set_ylabel(r'ATWD Voltage / mV')

                        filename = os.path.join(self.outputfolder,
                                                self.out_name + '_evt_{}.pdf')
                        exists = True
                        i = 0
                        while exists:
                            fname = filename.format(i)
                            if os.path.isfile(fname):
                                i += 1
                            else:
                                exists = False

                        print(fname)
                        fig.savefig(fname)
                        wf_cnt = 0
                        fig, ax = plt.subplots()

                waveform_series = wfs[omkey]
                for waveform in waveform_series:
                    wf_vect = np.array(waveform.waveform) / I3Units.mV
                    if np.sum(wf_vect) > WAVEFORM_THRESH:
                        start_time = waveform.time
                        bin_width = waveform.bin_width

                        time = np.linspace(start_time,
                                           start_time + bin_width * 128, 128)
                        ax.plot(time, wf_vect, label=omkey)
                        wf_cnt += 1

        elif self.string is not None and self.dom is not None:
            fig, ax = plt.subplots()
            key = OMKey(self.string, self.dom)
            ax.legend(loc='best')
            ax.set_xlabel(r'Time / ns')

            try:
                waveform_series = wfs[key]
            except KeyError:
                print('No waveforms found for this dom. Skipping this event!')
                return
            else:
                min_time = 0
                for waveform in waveform_series:
                    wf_vect = np.array(waveform.waveform) / I3Units.mV
                    start_time = waveform.time
                    bin_width = waveform.bin_width
                    if min_time == 0:
                        min_time = start_time

                    # Skip possible second launches
                    if len(wf_vect) == 128:
                        if start_time > min_time + 5000:
                            continue
                    elif len(wf_vect) == 256:
                        if start_time > min_time + 20000:
                            continue

                    time = np.linspace(start_time,
                                       start_time + bin_width * len(wf_vect),
                                       len(wf_vect))
                    ax.plot(time, wf_vect, label=key)
                    if len(wf_vect) == 128:
                        ax.set_ylabel(r'ATWD Voltage / mV')
                    elif len(wf_vect) == 256:
                        ax.set_ylabel('FADC Voltage / mV')

                filename = os.path.join(
                    self.outputfolder, self.out_name +
                    f'evt{self.evt_id}_str{self.string}_dom{self.dom}.png')
                if len(wf_vect) == 256:
                    filename = filename.replace('.png', '_fadc.png')
                print(filename)
                fig.savefig(filename)

        else:
            raise NotImplementedError()
Example #17
0
#!/usr/bin/env python

import unittest
from I3Tray import I3Tray, I3Units
from icecube import icetray, dataclasses, DomTools
from icecube.icetray import OMKey

doms = [OMKey(1, 1), OMKey(1, 2), OMKey(1, 3), OMKey(1, 4), OMKey(2, 4)]


def make_geometry():
    geo = dataclasses.I3Geometry()
    for omkey in doms:
        geo.omgeo[omkey] = dataclasses.I3OMGeo()
    geo.omgeo[icetray.OMKey(1, 1)].position = dataclasses.I3Position(0, 0, 0)
    geo.omgeo[icetray.OMKey(1, 2)].position = dataclasses.I3Position(0, 0, 50)
    geo.omgeo[icetray.OMKey(1, 3)].position = dataclasses.I3Position(0, 0, 100)
    geo.omgeo[icetray.OMKey(1, 4)].position = dataclasses.I3Position(0, 0, 500)
    geo.omgeo[icetray.OMKey(2,
                            4)].position = dataclasses.I3Position(0, 50, 500)
    return geo


def make_rpsmap():
    rpsmap = dataclasses.I3RecoPulseSeriesMap()
    for omkey in doms:
        rpsmap[omkey] = dataclasses.I3RecoPulseSeries()

    # time, width, and charge
    rp_properties = [(1650, 100, 0), (1850, 100, 1), (0, 100, 2), (550, 0, 3),
                     (800, 0, 4), (3500, 100, 5), (3500, 100, 6),
# generated by create_forced_lc.py

from icecube.icetray import OMKey

doms_to_plot = []
dom_targets = []

doms_to_plot.append({
    'name': "S09-D39",
    'T': -19.450003,
    'inice': "09-39",
    'scale': 150,
    'spe': 75000,
    'qpair': 5
})
dom_targets.append(OMKey(9, 37))
dom_targets.append(OMKey(9, 38))
dom_targets.append(OMKey(9, 39))
dom_targets.append(OMKey(9, 40))
dom_targets.append(OMKey(9, 41))

doms_to_plot.append({
    'name': "S41-D37",
    'T': -20.049994,
    'inice': "41-37",
    'scale': 150,
    'spe': 75000,
    'qpair': 5
})
dom_targets.append(OMKey(41, 35))
dom_targets.append(OMKey(41, 36))
            mcpe.npe = 1
            mcpe.time = photon.time #TODO: change to corrected time
            mcpeList.append(mcpe)
            photonList.append(photon)
    
    return mcpeList, photonList

# TODO: def getCorrectedTime(photon, omkey):

while( infile.more() ):
    frame = infile.pop_daq()
    photonDOMMap = frame["I3Photons"]
    mcpeMap = simclasses.I3MCPESeriesMap()
    succPhotonMap = simclasses.I3CompressedPhotonSeriesMap()
    for modkey in photonDOMMap.keys():
        mcpeList, photonList = generateMCPEList(photonDOMMap[modkey], modkey)
        omkey = OMKey(modkey.string, modkey.om, 0)
        if len(mcpeList) > 0:
            mcpeMap[omkey] = mcpeList
            succPhotonMap[modkey] = photonList
    
    frame["MCPESeriesMap"] = mcpeMap

    # only add frame to file if a hit was generated
    if passFrame(frame, mcpeMap.keys(), int(args.hitThresh), int(args.domThresh)):
        frame["SuccPhotonMap"] = succPhotonMap
        frame.Delete("I3Photons")
        outfile.push(frame)

outfile.close()
    def least_distance_to_polygon(fr):
        if fr.Has("I3Geometry"):
            geo_map = fr["I3Geometry"]
        else:
            print "ERROR: No I3Geometry in frame!"
            exit(1)

        #String numbers that defines the polygon. String 72 is repeated so that the polygon is closed when connecting those strings in order.
        if geometry == 'ic86':
            poly_strings = [72, 74, 50, 6, 1, 31, 75, 78]
        if geometry == 'ic79':
            poly_strings = [72, 74, 50, 6, 2, 41, 75, 78]
        # read in x,y coordinates from the gcd file for the polygon strings
        om = OMKey()
        gx = []
        gy = []
        for i in range(len(poly_strings)):
            om.string = poly_strings[i]
            om.om = 60
            gx += [geo_map.omgeo[om].position.x]
            gy += [geo_map.omgeo[om].position.y]

        #print "polygon x coordinates: ", gx
        #print "polygon y coordinates: ", gy

        # pull the x,y coordinates of string 78, 72, and 74 for later usage
        x72 = gx[0]
        y72 = gy[0]
        x74 = gx[1]
        y74 = gy[1]
        x78 = gx[7]
        y78 = gy[7]

        # x,y coordinates for event vertex
        rx = fr[RecoVertex].x
        ry = fr[RecoVertex].y

        inside = point_in_polygon(gx, gy, rx, ry)

        if inside:
            print "Event vertex is inside the IC86 polygon. Now calculate the perpendicular distances to the polygon edges.."
            str_dist = []
            event_dist = []
            for i in range(1, len(poly_strings)):
                str_dist += [cal_distance(gx[i - 1], gy[i - 1], gx[i], gy[i])]
                event_dist += [cal_distance(rx, ry, gx[i - 1], gy[i - 1])]

            str_dist += [cal_distance(gx[-1], gy[-1], gx[0], gy[0])
                         ]  # add the last polygon edge to close the polygon
            event_dist += [cal_distance(rx, ry, gx[-1], gy[-1])
                           ]  # add the last polygon edge to close the polygon
            #print "str_dist: ", str_dist
            #print "event_dist: ", event_dist
            #event_to polystring_dist.pop() #remove the last repeated distances between event vertex and string 31
            """
             The perpendicular distances from an event vertex to one polygon edge is the height of the triangle formed by the event vertex and
             the two string which defines the polygon edge. According to Heron's theorem: area=sqrt(s(s-a)(s-b)(s-c)), semiperimeter s=1/2(a+b+c)
             Also, area=1/2*base*height. Hence, height=2*area/base=2*sqrt(s(s-a)(s-b)(s-c))/base. Here, the bases are the polygon edges.
            """

            triad_heights = []
            semiperimeters = []
            for i in range(1, len(str_dist)):
                semiperimeters += [
                    0.5 * (str_dist[i - 1] + event_dist[i - 1] + event_dist[i])
                ]
            semiperimeters += [
                0.5 * (str_dist[-1] + event_dist[-1] + event_dist[0])
            ]  # add the last polygon edge element to close the polygon
            #print "semiperimeter: ", semiperimeters

            for i in range(1, len(str_dist)):
                if semiperimeters[i - 1] * (semiperimeters[i - 1] - event_dist[
                        i - 1]) * (semiperimeters[i - 1] - str_dist[i - 1]) * (
                            semiperimeters[i - 1] - event_dist[i]) < 0:
                    triad_heights += [0]
                    continue
                triad_heights += [
                    2 * np.sqrt(semiperimeters[i - 1] *
                                (semiperimeters[i - 1] - event_dist[i - 1]) *
                                (semiperimeters[i - 1] - str_dist[i - 1]) *
                                (semiperimeters[i - 1] - event_dist[i])) /
                    str_dist[i - 1]
                ]
            if semiperimeters[-1] * (semiperimeters[-1] - event_dist[-1]) * (
                    semiperimeters[-1] - str_dist[-1]) * (semiperimeters[-1] -
                                                          event_dist[0]) > 0:
                triad_heights += [
                    2 * np.sqrt(semiperimeters[-1] *
                                (semiperimeters[-1] - event_dist[-1]) *
                                (semiperimeters[-1] - str_dist[-1]) *
                                (semiperimeters[-1] - event_dist[0])) /
                    str_dist[-1]
                ]  # add the last polygon edge element to close the polygon
            else:
                triad_heights += [0]
            """
            Now divide the polygon into three regions: region A: perpendicular distance to edge 78-72 is inside of the polygon; region B: perpendicular distances to both edges 78-72 and 72-74 are inside of the polygon; 
            region C: perpendicular distance to edge 72-74 is inside of the polygon. These three regions are formed by two perpendicular lines through string 72, w.r.t. line 78-72 and line 72-74 respectively.
            The two lines deviding these regions are defined as: l_{AB} := -(x78-x72)/(y78-y72)(x-x72)+y72; l_{BC} := -(x74-x72)/(y74-y72)(x-x72)+y72
            For points fall within region A, distance to edge 72-74 should not be considered as minimum distance to polygon edges. Likewise, points that fall within region B, both distances to edges 78-72 and 72-74 should not
            be considered, and for region C, distance to edge 78-72 should not be considered. 
            
            """
            # CAUTION: the following manipulation is dependent on the ordering of the triad_heights elements: distance to edge 72-74 is first element, while distance to edge 72-78 is last element.
            if (ry - y72 + (x78 - x72) / (y78 - y72) *
                (rx - x72)) >= 0:  # point in region A
                #print "point in region A!"
                del triad_heights[0]  #remove distance to edge 72-74

            elif ((ry - y72 + (x78 - x72) / (y78 - y72) *
                   (rx - x72)) < 0) and (
                       (ry - y72 + (x74 - x72) / (y74 - y72) *
                        (rx - x72)) < 0):  # point in region B
                #print "point in region B!"
                del triad_heights[0]
                del triad_heights[-1]

            elif (ry - y72 + (x74 - x72) / (y74 - y72) *
                  (rx - x72)) >= 0:  # point in region C
                #print "point in region C!"
                del triad_heights[-1]

            #print "Perpendicular distances to polygon edges: ", triad_heights
            print "Minimum perpendicular distance to polygon edges: ", min(
                triad_heights)
            print "Minimum distance to polygon corner strings: ", min(
                event_dist)

            least_dist_to_polygon = min(triad_heights)
            #if min(event_dist)<min(triad_heights):
            #    least_dist_to_polygon=min(event_dist)

            fr["LeastDistanceToPolygon" +
               outputname] = dataclasses.I3Double(least_dist_to_polygon)
            fr["LeastDistanceToCornerString" +
               outputname] = dataclasses.I3Double(min(event_dist))

        else:
            print "Event vertex is outside of the IC86 polygon.."
            fr["LeastDistanceToPolygon" +
               outputname] = dataclasses.I3Double(-1)
            fr["LeastDistanceToCornerString" +
               outputname] = dataclasses.I3Double(-1)
#!/usr/bin/env python
# generated by create_forced_lc.py

from icecube.icetray import OMKey

# target doms for which we harvest vzp data
targets = [(39,57),(32,57),(2,58),
           (31,58),(22,57),(73,58),
           (62,58),(64,58),(56,57),
           (1,57)]

doms_to_plot = []
dom_targets = []

doms_to_plot.append( {'name':"S39-D57",'T':-10.650000,'inice': "39-57",'scale': 150,'atwd_spe': 20,'fadc_spe': 75000,'qpair': 5})#2.5
dom_targets.append(OMKey(39,55))
dom_targets.append(OMKey(39,56))
dom_targets.append(OMKey(39,57))
dom_targets.append(OMKey(39,58))
dom_targets.append(OMKey(39,59))

#doms_to_plot.append( {'name':"S32-D57",'T':-9.650000,'inice': "32-57",'scale': 150,'spe': 75000,'qpair': 5})
# dom_targets.append(OMKey(32,55))
# dom_targets.append(OMKey(32,56))
# dom_targets.append(OMKey(32,57))
# dom_targets.append(OMKey(32,58))
# dom_targets.append(OMKey(32,59))

doms_to_plot.append( {'name':"S02-D58",'T':-10.650000,'inice': "02-58",'scale': 150,'atwd_spe': 22, 'fadc_spe': 75000, 'qpair': 5})#2.6
dom_targets.append(OMKey(2,56))
dom_targets.append(OMKey(2,57))
Example #22
0
import os
from icecube.icetray import OMKey
from icecube.simclasses import I3CylinderMap
import numpy as np

source_directory = os.environ['I3_SRC']

file = open(source_directory + "/ppc/resources/ice/dx.dat")
contents = []
for line in file:
    contents += [line.split()]

DOMs = []

for key in contents:
    DOMs.append( [OMKey( int(key[0]) , int(key[1]) ) , float(key[2])] ) # i contains string , OM_number , orientation of cable , and error on orientation

class AddCylinder(icetray.I3Module):

    def __init__(self,context):
        icetray.I3Module.__init__(self,context)
        self.AddParameter( "TopCylinder" , "Position of top of cylinder" , dataclasses.I3Position( 0 , 0 , 500 ))
        self.AddParameter( "BottomCylinder" , "Position of the bottom of cylinder" , dataclasses.I3Position( 0 , 0 , -500 ))
        self.AddParameter( "Radius" , "Radius of Cylinder" , 10)
        
    def Configure(self):
        self.top = self.GetParameter('TopCylinder')
        self.bottom = self.GetParameter('BottomCylinder')
        self.radius = self.GetParameter('Radius')
        
Example #23
0
        break
    elif (np.log10(frame['MCPrimary'].energy) <
          7) & (frame['MCPrimary'].dir.zenith * 180 / np.pi > 10):
        continue

    eventinfo = {}
    for omkey in frame['WaveformInfo'].keys():
        eventinfo[omkey] = {}
        eventinfo[omkey]['run_number'] = frame['I3EventHeader'].run_id
        eventinfo[omkey]['event_number'] = frame['I3EventHeader'].event_id
        eventinfo[omkey]['zenith'] = frame['MCPrimary'].dir.zenith
        eventinfo[omkey]['azimuth'] = frame['MCPrimary'].dir.azimuth
        eventinfo[omkey]['energy'] = np.log10(frame['MCPrimary'].energy)
        dom = int(omkey.split(',')[1])
        string = int(omkey.split(',')[0].split('(')[1])
        position = frame['I3Geometry'].omgeo[OMKey(string, dom)].position
        eventinfo[omkey]['x'] = position.x
        eventinfo[omkey]['y'] = position.y
        eventinfo[omkey]['z'] = position.z
        eventinfo[omkey]['ShowerCOG_x'] = frame['Laputop'].pos.x
        eventinfo[omkey]['ShowerCOG_y'] = frame['Laputop'].pos.y
        eventinfo[omkey]['ShowerCOG_z'] = frame['Laputop'].pos.z
        eventinfo[omkey]['ShowerCOG_time'] = frame['ShowerCOG'].time
        eventinfo[omkey]['ShowerCOG_zen'] = frame['ShowerPlane'].dir.zenith
        eventinfo[omkey]['ShowerCOG_az'] = frame['ShowerPlane'].dir.azimuth
        eventinfo[omkey]['m'] = frame['WaveformInfo'][omkey]['m']
        eventinfo[omkey]['s'] = frame['WaveformInfo'][omkey]['s']
        eventinfo[omkey]['charge'] = frame['WaveformInfo'][omkey]['Charge']
        eventinfo[omkey]['chargePe'] = frame['WaveformInfo'][omkey][
            'Charge_PE']
        eventinfo[omkey]['chargeVEM'] = frame['LaputopHLCVEM'][OMKey(
# generated by create_forced_lc.py

from icecube.icetray import OMKey

doms_to_plot = []
dom_targets = []

doms_to_plot.append({
    'name': "S59-D08",
    'T': -30.349997,
    'inice': "59-08",
    'scale': 150,
    'spe': 75000,
    'qpair': 5
})
dom_targets.append(OMKey(59, 6))
dom_targets.append(OMKey(59, 7))
dom_targets.append(OMKey(59, 8))
dom_targets.append(OMKey(59, 9))
dom_targets.append(OMKey(59, 10))

doms_to_plot.append({
    'name': "S75-D07",
    'T': -29.650000,
    'inice': "75-07",
    'scale': 150,
    'spe': 75000,
    'qpair': 5
})
dom_targets.append(OMKey(75, 5))
dom_targets.append(OMKey(75, 6))
Example #25
0
def fillDT(frame, Streams2=[icetray.I3Frame.DAQ]):
    if 'ATWDPortiaPulse' not in frame:
        print 'no pulse'
        return False
    
    # Get ATWD info
    calib_atwd = frame['CalibratedATWD']
    cleanData  = frame['CleanInIceRawData']

    # Get lumi point
    lumi_point = checkTimes(frame)
    if lumi_point < 0: 
        return False

    # Loop over OM Keys and get calibrated ATWD
    # Set SC pulses
    SC_DOMs = [OMKey(55,d) for d in SCDoms]
    for i in range(len(SCDoms)):
        
        # Make OMKey
        key        = OMKey(55,i)

        # Get DOM launch
        domlaunchs = cleanData.get(key)
        
        # Get Earliest time DOM launch
        domTime = -1
        passLC  = False
        for launch in domlaunchs:
            if domTime < launch.GetStartTime():
                domTime = launch.GetStartTime()
                passLC  = launch.GetLCBit()
        
        # Do not look at events where LCBit fail
        if not passLC: return False
        if domTime < 0: return False

        # Now we have start time, loop over calibrated
        # waveforms and keep the waveform that has shortest
        # time
        waveForms = calib_atwd.get(key)
        dT       = -999
        maxV     = -999
        for waveform in waveForms:
            if waveform.time <= domTime:
                # This is it, record info
                binSize  = waveform.GetBinWidth()
                startT   = waveform.GetStartTime()
                voltages = waveform.GetWaveform()
                for i in range(len(voltages)):
                    if maxV < voltages[i]:
                        maxV = voltages[i]
                        dT   = (i*binSize)/I3Units.ns
                break
        
        # Now save the wavetime, if non-negative
        if dT < 0: return False
        
        # Fill
        h_dT_perDom_perLumi[i][lumi_point]->Fill(dT)

    # end loop over doms
    return True
Example #26
0
def cutwavetime(frame, Streams6=[icetray.I3Frame.DAQ]):
    if 'ATWDPortiaPulse' not in frame:
        print 'no pulse'
        return False

    pulses = frame['ATWDPortiaPulse']
    domlaunch = frame['CleanInIceRawData']
    calib_atwd = frame['CalibratedATWD']

    # Get the point for a given luminosity based
    # on the timing information
    lumi_point = checkTimes(frame)

    # Define the SC string doms
    near_sc = [OMKey(55,d) for d in range(37, 51)]

    # Check if have enough pulses.  400 is from
    # Aya's code, so I will check why...
    h_npulse.Fill( len(pulses) )
    if lumi_point >= 0: h_npulse_perLumi[lumi_point].Fill( len(pulses) )
    if len(pulses) < 400:
        return False

    
    counter = 0
    max_time_diff = 0.0
    max_amp = 0
    m_NPE     = 0
    m_LCBit   = 0
    LEThres   = 0.01
    max_time_largestV = 0
    for omkey, portiapulse in pulses:
        if omkey in near_sc:

            # Load variables for plotting
            amplitude = portiapulse.GetAmplitude() / I3Units.volt
            NPE       = portiapulse.GetEstimatedNPE()
            letime = portiapulse.GetLETime()
            waveform_series = calib_atwd.get(omkey)
            m_LCBit         = portiapulse.GetLCBit()

            # Count above amplitude
            if amplitude > LEThres:
                counter += 1
            
            # Fill hists for timing info
            h_amp.Fill(amplitude)
            if lumi_point >= 0:
                h_amp_perLumi[lumi_point].Fill(amplitude)

            # Examine Time DIfference stuff
            for waveform in waveform_series:
                wavetime = waveform.time
                if wavetime < letime:
                    time_diff = (letime-wavetime) / I3Units.nanosecond
                    h_tDiff.Fill(time_diff)
                    if lumi_point >=0: 
                        h_tDiff_perLumi[lumi_point].Fill(time_diff)
                    if time_diff > max_time_diff:
                        max_time_diff = time_diff
                        m_NPE = NPE
                    if amplitude > max_amp:
                        max_amp = amplitude
                        max_time_largestV = time_diff

    # Actually place the cut now
    if counter < 14 : return False

    h_maxTDiff.Fill( max_time_diff )
    h_maxTDiff_vs_NPE.Fill(max_time_diff, m_NPE)
    if lumi_point >=0:
        h_maxTDiff_perLumi[lumi_point].Fill(max_time_diff)
        h_maxTDiff_vs_NPE_perLumi[lumi_point].Fill(max_time_diff, m_NPE)
        if m_LCBit !=0 : 
            h_maxTDiff_passLCBit_perLumi[lumi_point].Fill(max_time_diff)
        h_nDOM_perLumi[lumi_point].Fill( counter )
        h_nDOM_vs_maxTDiff_perLumi[lumi_point].Fill(counter, max_time_diff)
        h_maxTDiff_forMaxV_perLumi[lumi_point].Fill(max_time_largestV)
    # Hoping this will speed things up
    # by returning False...  not really
    # any noticable increase in speed
    return False
Example #27
0
def wavetimeCut(frame, Streams1=[icetray.I3Frame.DAQ]):

    global h_dt

    # Currently only works for SC2, will
    # always be true for SC1
    if "SC1" in m_config.SC:
        return True

    # Only placing requirement for 30,
    # 51, and 100% filters
    lumis = ["30", "51", "100"]
    if m_config.lumi not in lumis:
        return True

    # Get ATWD and DOM launch info
    calib_atwd = frame['CalibratedATWD']
    cleanData = frame['CleanInIceRawData']

    # Loop over OM Keys and get calibrated ATWD
    nearestDOMs = [OMKey(55, d) for d in range(37, 51)]
    maxLETime = 0
    for key, domlaunchs in cleanData:
        for i in range(len(nearestDOMs)):

            if key == nearestDOMs[i]:
                # Get earliest dom launch
                domTime = sys.float_info.max
                passLC = False
                for launch in domlaunchs:
                    if launch.time < domTime:
                        domTime = launch.time
                        passLC = launch.lc_bit

                # Not considering DOM when LCBit failed
                if not passLC: continue
                if domTime < 0: continue

                # Now have start time. Loop over calibrated
                # waveforms and keep waveform that is closest
                # to domlaunch time.
                Waveforms = calib_atwd.get(key)
                for waveform in Waveforms:
                    if waveform.time <= domTime:
                        binSize = waveform.binWidth
                        voltages = waveform.waveform
                        for j in range(len(voltages)):
                            Voltage = voltages[j] / I3Units.V
                            if m_config.p_lumi.lumiVThresh(
                                    m_config.lumi) < Voltage:
                                LETime = ((j * binSize)) / I3Units.ns
                                if LETime > maxLETime:
                                    maxLETime = LETime
                                    break  # done with loop since found waveform
                        break  # done with loop since found waveform

    # end loop over DOMs

    if maxLETime > m_config.p_lumi.lumiTimeCut(m_config.lumi):
        return False

    return True
Example #28
0
def OfflineCalibration(tray, name, InIceOutput='InIcePulses',
                       IceTopOutput='IceTopPulses',
                       BadDOMList='BadDomsListSLC',
                       WavedeformSPECorrections=False,
                       pass2=False):
    """
    Re-do calibration and feature extraction for those launches that were
    sent in raw form, unifying the results with the pulses sent as SuperDST
    only. Also performs bad-DOM cleaning on the final output pulses.

    :param InIceOutput: Name of output pulse series with in-ice pulses
    :param IceTopOutput: Name of output pulse series with IceTop pulses
    """

    # Extract DOMLaunches and triggers from raw DAQ data
    tray.AddSegment(payload_parsing.I3DOMLaunchExtractor,
        name+'/domlaunchextractor',
        BufferID='I3DAQData',
        TriggerID='I3TriggerHierarchyTrimmed',
        SpecialDataID = "SpecialHits",
        SpecialDataOMs = [OMKey(0,1),
                          OMKey(12,65),
                          OMKey(12,66),
                          OMKey(62,65),
                          OMKey(62,66)]
    )

    # Extract DOMLaunches and triggers from SDST seatbelted raw DAQ data
#    tray.AddModule('I3FrameBufferDecode', name+'/trimmeddecode',
#        BufferID='I3DAQDataTrimmed', If=lambda fr: not 'I3DAQData' in fr)
    tray.AddSegment(payload_parsing.I3DOMLaunchExtractor,
        name+'/domlaunchextractorTrimmedDecode',
        BufferID='I3DAQDataTrimmed',
        TriggerID='I3TriggerHierarchyTrimmed',
        SpecialDataID = "SpecialHits",
        SpecialDataOMs = [OMKey(0,1),
                          OMKey(12,65),
                          OMKey(12,66),
                          OMKey(62,65),
                          OMKey(62,66)],
        If = lambda fr: not 'I3DAQData' in fr
    )


    def cleanuppointlessdaqdata(frame, data):
        if data in frame and len(frame[data]) == 0: del frame[data]
    tray.AddModule(cleanuppointlessdaqdata, name+'/pointlessInIceRawData',
        data='InIceRawData', Streams=[icetray.I3Frame.DAQ])
    tray.AddModule(cleanuppointlessdaqdata, name+'/pointlessIceTopRawData',
        data='IceTopRawData', Streams=[icetray.I3Frame.DAQ])
    if pass2:
        # PFDST files already have the extracted IceTop launches, and they
        # are apparently not included in I3DAQDataTrimmed. 
        # As a result, the code above will have renamed the iceTopRawData
        # to IceTopRawData_orig, extracted a new, empty version, and then
        # deleted the new version for being empty. So, we rename the
        # original back. 
        tray.AddModule("Rename",name+"/restore_PFDST_IceTop_launches",
            Keys=["IceTopRawData_orig","IceTopRawData"],
            If=lambda fr: not 'IceTopRawData' in fr)

    # Reextract pulses if necessary (and calibration errata for
    # reconstructions!)
    tray.AddModule('I3DOMLaunchCleaning', name + '/domlaunchcleaning',
        CleanedKeysList=BadDOMList)
    tray.AddSegment(InIceCalibration, name + '/inicecal',
        InputLaunches='CleanInIceRawData',
        OutputPulses='Reextracted' + InIceOutput,
        WavedeformSPECorrections=WavedeformSPECorrections)
    tray.AddSegment(IceTopCalibration, name + '/icetopcal',
        InputLaunches='CleanIceTopRawData',
        OutputPulses='Reextracted' + IceTopOutput)

    # Make the set of DST-only pulses for merging
    def SuperDSTOnlyPulses(frame, launches, inpulses, outpulses):
        mask = dataclasses.I3RecoPulseSeriesMapMask(frame,
            inpulses, lambda omkey, index, pulse:
            (not launches in frame or not omkey in frame[launches])
            and not omkey in frame[BadDOMList])
        if mask.any():
            frame[outpulses] = mask
    tray.AddModule(SuperDSTOnlyPulses, name + '/inicedstonlypulses',
        launches = 'InIceRawData', inpulses = 'InIceDSTPulses',
        outpulses = 'InIceDSTOnlyPulses', Streams=[icetray.I3Frame.DAQ])
    tray.AddModule(SuperDSTOnlyPulses, name + '/icetopdstonlypulses',
        launches = 'IceTopRawData', inpulses = 'IceTopDSTPulses',
        outpulses = 'IceTopDSTOnlyPulses', Streams=[icetray.I3Frame.DAQ])
    
    # Merge DST-only and offline reconstructed pulses
    def dstofflinemerge(frame, Output='', Input=[]):
        rootpulses = []
        for i in Input:
            if not i in frame:
                continue
            rootpulses.append(i)
        frame[Output] = dataclasses.I3RecoPulseSeriesMapUnion(frame,
            rootpulses)
    tray.AddModule(dstofflinemerge, name + '/dstofflineinicemerge',
        Output=InIceOutput,
        Input=['InIceDSTOnlyPulses', 'Reextracted' + InIceOutput],
        Streams=[icetray.I3Frame.DAQ])
    tray.AddModule(dstofflinemerge, name + '/dstofflineicetopmerge',
        Output=IceTopOutput,
        Input=['IceTopDSTOnlyPulses', 'Reextracted' + IceTopOutput,
         'Reextracted' + IceTopOutput + '_SLC'],
        Streams=[icetray.I3Frame.DAQ])

    # Clean up miscellaneous garbage we either added or inherited from PNF 
    tray.AddModule('Delete', name+'/cleanup',
        Keys=['I3TriggerHierarchyTrimmed', 'DrivingTime',
        'I3EventHeader_orig', 'I3DAQDataTrimmed', 'I3DAQData'])
Example #29
0
def get_fit(frame, tol):
    pass_value = True
    true_zen = frame['MCPrimary'].dir.zenith
    true_az = frame['MCPrimary'].dir.azimuth

    true_x, true_y, true_z = get_n_cos(true_zen, true_az)

    tc = frame['ShowerCOG'].time
    xc = frame['ShowerCOG'].pos.x
    yc = frame['ShowerCOG'].pos.y
    zc = frame['ShowerCOG'].pos.z
    zen_shower = frame['ShowerPlane'].dir.zenith
    az_shower = frame['ShowerPlane'].dir.azimuth

    x_start, y_start, z_start = get_n_cos(zen_shower, az_shower)
    a_start = 4.823 * 10**-4
    b_start = 19.51
    sigma_start = 83.5

    x_o = []
    y_o = []
    z_o = []
    r_o = []
    t0_o = []
    check = []
    remove_index_list = []
    count = 0
    for omkey in frame['WaveformInfo'].keys():
        dom = int(omkey.split(',')[1])
        string = int(omkey.split(',')[0].split('(')[1])
        position = frame['I3Geometry'].omgeo[OMKey(string, dom)].position
        x_o.append(position.x)
        y_o.append(position.y)
        z_o.append(position.z)
        r_o.append(
            ((position.x)**2.0 + (position.y)**2.0 + (position.z)**2.0)**0.5)
        t0_o.append(frame['WaveformInfo'][omkey]['t_0'])
        if frame['WaveformInfo'][omkey]['t_0'] == 0:
            check.append(False)
            remove_index_list.append(count)
        elif abs(frame['WaveformInfo'][omkey]['t_0'] -
                 frame['WaveformInfo'][omkey]['StartTime']) > 50:
            check.append(False)
            remove_index_list.append(count)
        else:
            check.append(True)
        count += 1

    x_o = np.array(x_o)
    y_o = np.array(y_o)
    z_o = np.array(z_o)
    r_o = np.array(r_o)
    t0_o = np.array(t0_o)

    get_t_new = partial(get_t, tc=tc, xc=xc, yc=yc, zc=zc)

    try:
        fit_original = curve_fit(
            get_t_new, (x_o, y_o, z_o, r_o),
            t0_o,
            p0=[x_start, y_start, z_start, a_start, b_start, sigma_start],
            bounds=((-1, -1, -1, 0, 0, 0), (1, 1, 0, 2e-3, 200, 500)),
            maxfev=3000,
            absolute_sigma=True)
        vector_list = []
        fit_list = []
        mag_list = [0]
        x, y, z = get_n(fit_original[0][0], fit_original[0][1],
                        fit_original[0][2])
        vector_list.append(np.array([x, y, z]))
        fit_list.append(fit_original)
    except RuntimeError:
        final_fit = None
        check1 = check
        fit_status = False
        pass_value = False

    count = 0

    while pass_value:
        if count == 0:
            check1 = np.copy(check)
        else:
            check1[remove_index] = False

        fit_check = []
        removed = []
        vector_check_list = []

        for i in np.array(range(len(check1))):
            check2 = np.copy(check1)
            check2[i] = False

            if (i in remove_index_list):
                continue

            x = x_o[check2]
            y = y_o[check2]
            z = z_o[check2]
            r = r_o[check2]
            t0 = t0_o[check2]

            try:
                fit = curve_fit(get_t_new, (x, y, z, r),
                                t0,
                                p0=[
                                    fit_list[-1][0][0], fit_list[-1][0][1],
                                    fit_list[-1][0][2], fit_list[-1][0][3],
                                    fit_list[-1][0][4], fit_list[-1][0][5]
                                ],
                                bounds=((-1, -1, -1, 0, 0, 0), (1, 1, 0, 2e-3,
                                                                200, 500)),
                                maxfev=5000,
                                absolute_sigma=True)
            except RuntimeError:
                continue

            fit_check.append(fit)
            x, y, z = get_n(fit[0][0], fit[0][1], fit[0][2])
            vector_check_list.append([x, y, z])
            removed.append(i)

        x_1, y_1, z_1 = get_n(fit_list[-1][0][0], fit_list[-1][0][1],
                              fit_list[-1][0][2])

        theta = np.arctan(((x_1**2.0 + y_1**2.0)**0.5) / z_1)

        output = space_angle_diff(vector_list[-1], vector_check_list)

        mag = [
            magnitude_spherical(theta, d_theta, d_phi)**0.5
            for d_theta, d_phi in output
        ]

        remove_index = removed[np.argmax(mag)]
        remove_index_list.append(remove_index)

        fit_list.append(fit_check[np.argmax(mag)])

        mag_list.append(mag[np.argmax(mag)])

        vector1 = np.sum(vector_check_list, axis=0) / len(vector_check_list)
        vector2 = np.array([x_1, y_1, z_1])
        bias = (len(vector_check_list) - 1) * (vector1 - vector2)
        count += 1

        if (abs(mag_list[-1] - mag_list[-2]) < tol):
            check1[remove_index] = False
            final_fit = fit_check[np.argmax(mag)]
            x_final, y_final, z_final = get_n(final_fit[0][0], final_fit[0][1],
                                              final_fit[0][2])
            ang_diff_final = get_ang_diff(x_final, y_final, z_final, true_x,
                                          true_y, true_z)
            fit_status = True
            break

    return final_fit, check1, fit_status