Ejemplo n.º 1
0
def I3CLSimMakePhotonsWithServer(tray, name,
                       ServerAddress,
                       DetectorSettings,
                       MCTreeName="I3MCTree",
                       OutputMCTreeName=None,
                       FlasherInfoVectName=None,
                       FlasherPulseSeriesName=None,
                       PhotonSeriesName="PhotonSeriesMap",
                       MCPESeriesName="MCPESeriesMap",
                       RandomService=None,
                       ParticleHistory=False,
                       ParticleHistoryGranularity=20*icetray.I3Units.m,
                       ExtraArgumentsToI3CLSimClientModule=dict(),
                       If=lambda f: True
                       ):
    """
    Propagate particles and photons up to PE level.
    Reads its particles from an I3MCTree and writes either an
    I3CompressedPhotonSeriesMap, an I3MCPESeriesMap, or both.

    Photon propagation is delegated to the I3CLSimServer listening at
    ServerAddress. This server may be shared by multiple client processes to
    maximize GPU utilization.

    If MMCTrackListName is set, this segment will assume that MMC has been
    applied to the I3MCTree and that MMC was *NOT* run using the "-recc"
    option.

    :param ServerAddress:
        The 0MQ address of an I3CLSimServer 
    :param DetectorSettings:
        The output of clsim.traysegments.common.setupDetector. These should be
        the same as those used to configure the server.
    :param MCTreeName:
        The name of the I3MCTree containing the particles to propagate.
    :param OutputMCTreeName:
        A copy of the (possibly sliced) MCTree will be stored as this name.
    :param FlasherInfoVectName:
        Set this to the name of I3FlasherInfoVect objects in the frame to
        enable flasher simulation. The module will read I3FlasherInfoVect objects
        and generate photons according to assumed parameterizations.
    :param FlasherPulseSeriesName:
        Set this to the name of an I3CLSimFlasherPulseSeries object in the frame to
        enable flasher/Standard Candle simulation.
        This cannot be used at the same time as FlasherInfoVectName.
        (I3CLSimFlasherPulseSeries objects are clsim's internal flasher
        representation, if "FlasherInfoVectName" is used, the I3FlasherInfoVect
        objects are converted to I3CLSimFlasherPulseSeries objects.)
    :param PhotonSeriesName:
        Configure this to enable writing an I3CompressedPhotonSeriesMap containing
        all photons that reached the DOM surface. If this is set to None,
        photons will be converted to PE immediately, drastically reducing
        memory overhead for bright events.
    :param MCPESeriesName:
        Configure this to enable writing an I3MCPESeriesMap.
    :param RandomService:
        Set this to an instance of a I3RandomService. Alternatively,
        you can specify the name of a configured I3RandomServiceFactory
        added to I3Tray using tray.AddService(). If you don't configure
        this, the default I3RandomServiceFactory will be used.
    :param ParticleHistory:
        Store secondary particles produced by particle propagators (e.g.
        Geant4, PROPOSAL) in the MCTree.
    :param ParticleHistoryGranularity:
        When storing history in the MCTree, coalesce secondary EM cascades that
        are less than this distance apart.
    :param If:
        Python function to use as conditional execution test for segment modules.        
    :returns: the dictionary of keyword arguments passed to I3CLSimClientModule
    """
    from icecube import icetray, dataclasses, phys_services, clsim

    # make sure the geometry is updated to the new granular format (in case it is supported)
    if hasattr(dataclasses, "I3ModuleGeo"):
        tray.AddModule("I3GeometryDecomposer", name + "_decomposeGeometry",
                       If=lambda frame: If(frame) and ("I3OMGeoMap" not in frame) and ("I3ModuleGeoMap" not in frame))

    if MCTreeName is None or MCTreeName=="":
        clSimMCTreeName=""
        if ChopMuons:
            raise RuntimeError("You cannot have \"MMCTrackListName\" enabled with no MCTree!")
    else:
        clSimMCTreeName=MCTreeName

    if FlasherInfoVectName is None or FlasherInfoVectName=="":
        if (FlasherPulseSeriesName is not None) and (FlasherPulseSeriesName!=""):
            SimulateFlashers=True
            clSimFlasherPulseSeriesName = FlasherPulseSeriesName
            clSimOMKeyMaskName = ""
        else:
            SimulateFlashers=False
            clSimFlasherPulseSeriesName = ""
            clSimOMKeyMaskName = ""
    else:
        if (FlasherPulseSeriesName is not None) and (FlasherPulseSeriesName!=""):
            raise RuntimeError("You cannot use the FlasherPulseSeriesName and FlasherInfoVectName parameters at the same time!")
        
        SimulateFlashers=True
        clSimFlasherPulseSeriesName = FlasherInfoVectName + "_pulses"
        clSimOMKeyMaskName = FlasherInfoVectName + "_OMKeys"
        
        tray.AddModule(clsim.FlasherInfoVectToFlasherPulseSeriesConverter,
                       name + "_FlasherInfoVectToFlasherPulseSeriesConverter",
                       FlasherInfoVectName = FlasherInfoVectName,
                       FlasherPulseSeriesName = clSimFlasherPulseSeriesName,
                       FlasherOMKeyVectName = clSimOMKeyMaskName,
                       If=If)

    if (OutputMCTreeName is not None) and (OutputMCTreeName != ""):
        # copy the MCTree to the requested output name
        def copyMCTree(frame, inputName, outputName, If_=None):
            if If_ is not None:
                if not If_(frame): return
            frame[outputName] = frame[inputName]
        tray.AddModule(copyMCTree, name + "_copyMCTree",
                       inputName=clSimMCTreeName,
                       outputName=OutputMCTreeName,
                       Streams=[icetray.I3Frame.DAQ],
                       If_=If)
        clSimMCTreeName = OutputMCTreeName
    else:
        clSimMCTreeName = clSimMCTreeName

    clsimModuleArgs = {
        'ServerAddress': ServerAddress,
        'PhotonSeriesMapName': PhotonSeriesName,
        'MCTreeName': clSimMCTreeName,
        'FlasherPulseSeriesName': clSimFlasherPulseSeriesName,
        'IgnoreSubdetectors': DetectorSettings['IgnoreSubdetectors'],
        'PhotonSeriesMapName': PhotonSeriesName or '',
        'MCPESeriesMapName': MCPESeriesName or '',
        'If': If,
    }
    clsimModuleArgs.update(**ExtraArgumentsToI3CLSimClientModule)

    # Set up light source -> step conversion if not already configured
    # This allows step generators with expensive initialization to be reused
    if not 'StepGenerator' in clsimModuleArgs:
        stepGenerator = clsim.I3CLSimLightSourceToStepConverterAsync(1)
        stepGenerator.SetLightSourceParameterizationSeries(DetectorSettings['ParameterizationList'])
        stepGenerator.SetMediumProperties(DetectorSettings['MediumProperties'])
        stepGenerator.SetRandomService(RandomService)
        stepGenerator.SetWlenBias(DetectorSettings['WavelengthGenerationBias'])
        propagators = []
        if DetectorSettings['UseI3PropagatorService']:
            from icecube.simprod.segments.PropagateMuons import make_standard_propagators
            pmap = make_standard_propagators(EmitTrackSegments=True, SplitSubPeVCascades=False)
            propagators.append(clsim.I3CLSimLightSourcePropagatorFromI3PropagatorService(pmap,ParticleHistory,ParticleHistoryGranularity))

        if DetectorSettings['UseGeant4']:
            propagators.append(clsim.I3CLSimLightSourcePropagatorGeant4(collectParticleHistory=ParticleHistory))

        stepGenerator.SetPropagators(propagators);
        clsimModuleArgs['StepGenerator'] = stepGenerator

    if clsimModuleArgs['MCPESeriesMapName']:
        # convert photons to MCPE in the worker thread of I3CLSimClientModule
        clsimModuleArgs['MCPEGenerator'] = clsim.I3CLSimPhotonToMCPEConverterForDOMs(
            RandomService,
            DetectorSettings['WavelengthAcceptance'],
            DetectorSettings['AngularAcceptance']
        )

    tray.AddModule('I3CLSimClientModule', name+"_makePhotons",
        **clsimModuleArgs
    )

    if MCPESeriesName:
        class GatherStatistics(icetray.I3Module):
            """Mimick the summary stage of I3PhotonToMCPEConverter::Finish()"""
            def __init__(self, ctx):
                icetray.I3Module.__init__(self, ctx)
                self.nhits = 0
            def DAQ(self, frame):
                self.nhits += sum((h.npe for hits in frame[MCPESeriesName].values() for h in hits))
                self.PushFrame(frame)
            def Finish(self):
                if not 'I3SummaryService' in self.context:
                    return
                summary = self.context['I3SummaryService']
                prefix = 'I3PhotonToMCPEConverter_'+name+'_makeHitsFromPhotons_clsim_make_hits_'
                summary[prefix+'NumGeneratedHits'] = self.nhits
        tray.Add(GatherStatistics)

    return clsimModuleArgs
Ejemplo n.º 2
0
        if barrierWasReset:
            break

    n_clsim = len(photons['clsim'])
    #pprint('total unweighted clsim: %d photons  ' %   n_clsim )

    n_clsim = sum([p.weight for p in photons['clsim']])

    #pprint('total weighted clsim: %d photons  ' %   n_clsim )

    # Down-convert to MCPEs. If the Cherenkov photon generator is configured
    # correctly, this should remove any constant or wavelength-dependent scale
    # factors that may be present in the raw number of detected photons.
    hitter = clsim.I3CLSimPhotonToMCPEConverterForDOMs(
        rng, DetectorParams['WavelengthAcceptance'],
        DetectorParams['AngularAcceptance'])

    def generate_mcpe(photons):
        for clsim_photon in photons:
            p = simclasses.I3CompressedPhoton()
            p.dir = clsim_photon.dir
            p.pos = clsim_photon.pos
            p.time = clsim_photon.time
            p.wavelength = clsim_photon.wavelength
            p.weight = clsim_photon.weight
            key = dataclasses.ModuleKey(clsim_photon.stringID,
                                        clsim_photon.omID)
            hit = hitter.Convert(key, p)
            if hit:
                yield hit[1]
Ejemplo n.º 3
0
def I3CLSimMakeHitsFromPhotons(
        tray,
        name,
        PhotonSeriesName="PhotonSeriesMap",
        MCPESeriesName="MCPESeriesMap",
        RandomService=None,
        DOMOversizeFactor=5.,
        UnshadowedFraction=1.0,
        IceModelLocation=None,  #Needed for icemodel-dependent efficiency
        HoleIceParameterization=expandvars(
            "$I3_BUILD/ice-models/resources/models/angsens/as.h2-50cm"),
        MergeHits=False,
        GCDFile=None,
        If=lambda f: True):
    """
    Convert I3Photons into I3MCPEs. This applies the DOM
    angular acceptance (and wavenelgth acceptance in case
    you are using the unbiased photon propagation mode.)

    :param PhotonSeriesName:
        Name of the input I3PhotonSeriesMap to be converted.
    :param MCPESeriesName:
        Name of the output I3MCPESeriesMap written by the module.
        Set this to None to prevent generating MCPEs from
        Photons.
    :param RandomService:
        Set this to an instance of a I3RandomService. Alternatively,
        you can specify the name of a configured I3RandomServiceFactory
        added to I3Tray using tray.AddService(). If you don't configure
        this, the default I3RandomServiceFactory will be used.
    :param DOMOversizeFactor:
        Set the DOM oversize factor. To disable oversizing, set this to 1.
    :param UnshadowedFraction:
        Fraction of photocathode available to receive light (e.g. unshadowed by the cable)
    :param HoleIceParameterization:
        Set this to a hole ice parameterization file. The default file contains the 
        coefficients for nominal angular acceptance correction due to hole ice (ice-models 
        project is required). Use file $I3_BUILD/ice-models/resources/models/angsens/as.nominal 
        for no hole ice parameterization. 
    :param MergeHits:
    	Set to true to perform time merging on the MCPE as they are produced. This is useful for 
    	reducing the memory and disk space used by high energy (bright) events, and can allow 
    	detector simulation to run much more quickly. This causes parent particle information to be 
    	stored in an additional frame object. 
    :param If:
        Python function to use as conditional execution test for segment modules.        
    """

    from icecube import clsim
    from icecube.clsim.traysegments.common import setupDetector

    DetectorSettings = setupDetector(
        GCDFile=GCDFile,
        IceModelLocation=IceModelLocation,
        DOMOversizeFactor=DOMOversizeFactor,
        UnshadowedFraction=UnshadowedFraction,
        HoleIceParameterization=HoleIceParameterization,
    )

    MCPEGenerator = clsim.I3CLSimPhotonToMCPEConverterForDOMs(
        RandomService, DetectorSettings['WavelengthAcceptance'],
        DetectorSettings['AngularAcceptance'])

    tray.AddModule("I3PhotonToMCPEConverter",
                   name + "_clsim_make_hits",
                   MCPEGenerator=MCPEGenerator,
                   InputPhotonSeriesMapName=PhotonSeriesName,
                   OutputMCPESeriesMapName=MCPESeriesName,
                   MergeHits=MergeHits,
                   If=If)