def get_pmt_surface(): data = np.genfromtxt('config/qe_curve.dat', delimiter=',') wavelength = data[:, 0] efficiency = data[:, 1] r8486_pmt = Surface('R8486 PMT') r8486_pmt.set('detect', efficiency, wavelength) return r8486_pmt
def get_mirror_surface(): data = np.genfromtxt('config/gold_reflectivity.dat', delimiter=',') wavelength = data[:, 0] reflectivity = data[:, 1] / 100 specular_percent = 0.995 #This is the % of reflectance that is specular diffuse_percent = 1 - specular_percent gold_mirror = Surface('EO mirror') gold_mirror.set('absorb', 1 - reflectivity, wavelength) gold_mirror.set('reflect_specular', specular_percent * reflectivity, wavelength) gold_mirror.set('reflect_diffuse', diffuse_percent * reflectivity, wavelength) return gold_mirror
def make_glass_surface(): # mostly fake numbers based on http://www.shimadzu.com/an/uv/support/uv/ap/measuring_solar2.html # glass mostly absorbs until 300 nm, then gradually transmits. reflected light assumed diffuse glass_surface = Surface("glass_surface") glass_surface.set( 'reflect_diffuse', np.array([(100, 0.0), (280.0, 0.0), (350.0, 0.5), (1000.0, 0.5)])) glass_surface.set( 'reflect_specular', np.array([(100, 0.0), (280.0, 0.0), (350.0, 0.5), (1000.0, 0.5)])) glass_surface.set( 'absorb', np.array([(100, 1.0), (280.0, 1.0), (350.0, 0.0), (1000.0, 0.0)])) glass_surface.set('detect', 0.0) glass_surface.set('reemit', 0.0) glass_surface.transmissive = 1 return glass_surface
def make_titanium_surface(): titanium_surface = Surface("titanium_surface") titanium_surface.set('reflect_diffuse', 0.125) titanium_surface.set('reflect_specular', 0.125) titanium_surface.set('detect', 0.0) titanium_surface.set('absorb', 0.75) titanium_surface.set('reemit', 0.0) titanium_surface.transmissive = 0 return titanium_surface
def make_steel_surface(): steel_surface = Surface("steel_surface") steel_surface.set('reflect_diffuse', 0.25) steel_surface.set('reflect_specular', 0.0) steel_surface.set('detect', 0.0) steel_surface.set('absorb', 0.75) steel_surface.set('reemit', 0.0) steel_surface.transmissive = 0 # eta and kappa not set return steel_surface
def make_absorbing_surface(name="absorbing_surface"): # mostly fake numbers based on http://www.shimadzu.com/an/uv/support/uv/ap/measuring_solar2.html # glass mostly absorbs until 300 nm, then gradually transmits. reflected light assumed diffuse black_surface = Surface(name) black_surface.set('reflect_diffuse', 0.0) black_surface.set('reflect_specular', 0.0) black_surface.set('absorb', 1.0) black_surface.set('detect', 0.0) black_surface.set('reemit', 0.0) black_surface.transmissive = 0 return black_surface
import numpy as np from chroma.geometry import Material, Surface vacuum = Material('vacuum') vacuum.set('refractive_index', 1.0) vacuum.set('absorption_length', 1e6) vacuum.set('scattering_length', 1e6) lambertian_surface = Surface('lambertian_surface') lambertian_surface.set('reflect_diffuse', 1) black_surface = Surface('black_surface') black_surface.set('absorb', 1) shiny_surface = Surface('shiny_surface') shiny_surface.set('reflect_specular', 1) glossy_surface = Surface('glossy_surface') glossy_surface.set('reflect_diffuse', 0.5) glossy_surface.set('reflect_specular', 0.5) red_absorb_surface = Surface('red_absorb') red_absorb_surface.set('absorb', [0.0, 0.0, 1.0], [465, 545, 685]) red_absorb_surface.set('reflect_diffuse', [1.0, 1.0, 0.0], [465, 545, 685]) # r7081hqe photocathode material surface # source: hamamatsu supplied datasheet for r7081hqe pmt serial number zd0062 r7081hqe_photocathode = Surface('r7081hqe_photocathode') r7081hqe_photocathode.detect = \ np.array([(260.0, 0.00), (270.0, 0.04), (280.0, 0.07), (290.0, 0.77), (300.0, 4.57),
lensmat.set('refractive_index', lensmat_refractive_index) lensmat.set('absorption_length', 1e8) lensmat.set('scattering_length', 1e8) lensmat_ohara = Material('lensmat_ohara') lensmat_ohara.set('refractive_index', lensmat_ohara_refractive_index) lensmat_ohara.set('absorption_length', 1e8) lensmat_ohara.set('scattering_length', 1e8) blackhole = Material('blackhole') blackhole.set('refractive_index', 1.0) blackhole.set('absorption_length', 1e-15) blackhole.set('scattering_length', 1e8) #creates a surface with complete detection-- used on pmt fulldetect = Surface('fulldetect') fulldetect.set('detect', 1.0) #creates a surface with complete absorption-- used on volume boundary (previously flat pmt detecting surface) fullabsorb = Surface('fullabsorb') fullabsorb.set('absorb', 1.0) noreflect = Surface('noreflect') #noreflect.transmissive = 1.0 noreflect.model = 2 mirror = Surface('mirror') mirror.set('reflect_specular', 1.0) # myglass = Material('glass') # myglass.set('refractive_index', 1.49)
bulk_absorb = IntCol() surface_detect = IntCol() surface_absorb = IntCol() surface_reemit = IntCol() def reset(self): self.reflect_diffuse = 0 self.reflect_specular = 0 self.bulk_scatter = 0 self.bulk_absorb = 0 self.surface_detect = 0 self.surface_absorb = 0 self.surface_reemit = 0 uboone_wireplane = Surface('uboone_wireplane') uboone_wireplane.nplanes = 3.0 uboone_wireplane.wire_pitch = 0.3 uboone_wireplane.wire_diameter = 0.015 uboone_wireplane.transmissive = 1 uboone_wireplane.model = Surface.SURFACE_WIREPLANE def add_wireplane_surface(solid): # function detector class will use to add a wireplane surface to the geometry # set surface for triangles on x=-1281.0 plane for n, triangle in enumerate(solid.mesh.triangles): nxplane = 0 for ivert in triangle: if solid.mesh.vertices[ivert, 0] == -1281.0: nxplane += 1
def get_sipm_surface(): wavelength = np.arange(100, 600, 0.5) hamamatsu_sipm = Surface('Hamamatsu SiPM') hamamatsu_sipm.set('detect', np.ones(len(wavelength)), wavelength) return hamamatsu_sipm
def surfacesdict(self): # Steel/LAr steel_surface = Surface("steel_surface") steel_surface.set('reflect_diffuse', 0.25) steel_surface.set('reflect_specular', 0.0) steel_surface.set('detect', 0.0) steel_surface.set('absorb', 0.75) steel_surface.set('reemit', 0.0) steel_surface.transmissive = 0 # Titanium/LAr titanium_surface = Surface("titanium_surface") titanium_surface.set('reflect_diffuse', 0.125) titanium_surface.set('reflect_specular', 0.125) titanium_surface.set('detect', 0.0) titanium_surface.set('absorb', 0.75) titanium_surface.set('reemit', 0.0) titanium_surface.transmissive = 0 # Glass/LAr glass_surface = Surface("glass_surface") glass_surface.set( 'reflect_diffuse', np.array([(100, 0.0), (280.0, 0.0), (350.0, 0.5), (1000.0, 0.5)])) glass_surface.set( 'reflect_specular', np.array([(100, 0.0), (280.0, 0.0), (350.0, 0.5), (1000.0, 0.5)])) glass_surface.set( 'absorb', np.array([(100, 1.0), (280.0, 1.0), (350.0, 0.0), (1000.0, 0.0)])) glass_surface.set('detect', 0.0) glass_surface.set('reemit', 0.0) glass_surface.transmissive = 1 # Acrylic: detecting surface acrylic_surface = Surface("acrylic_surface_detector") acrylic_surface.set('reflect_diffuse', 0.0) acrylic_surface.set('reflect_specular', 0.0) acrylic_surface.set('detect', 1.0) acrylic_surface.set('absorb', 0.0) acrylic_surface.set('reemit', 0.0) acrylic_surface.transmissive = 0 # Acrylic: wavelength shifting #acrylic_surface_wls = Surface("acrylic_surface_wls") #acrylic_surface_wls.set('reflect_diffuse', 0.0) #acrylic_surface_wls.set('reflect_specular',0.0) #acrylic_surface_wls.set('detect',0.0) #acrylic_surface_wls.set('absorb',0.0) #acrylic_surface_wls.set('reemit', load_hist_data( os.path.dirname(__file__)+"/raw_tpb_emission.dat", 350, 640 ) ) # 100% reemission. Actually, should be 120%!! Need to think about this. #acrylic_surface_wls.transmissive = 1 # G10 g10_surface = Surface("g10_surface") g10_surface.set('reflect_diffuse', 0.5) g10_surface.set('reflect_specular', 0.0) g10_surface.set('detect', 0.0) g10_surface.set('absorb', 0.5) g10_surface.set('reemit', 0.0) g10_surface.transmissive = 0 # Black surface black_surface = Surface("black_surface") black_surface.set('reflect_diffuse', 0.0) black_surface.set('reflect_specular', 0.0) black_surface.set('absorb', 1.0) black_surface.set('detect', 0.0) black_surface.set('reemit', 0.0) black_surface.transmissive = 0 #boundary_surfaces = { ("STEEL_STAINLESS_Fe7Cr2Ni", "LAr"):black_surface, # ("Titanium", "LAr"):black_surface, # ("Acrylic", "LAr"):acrylic_surface, # ("G10", "LAr"):black_surface, # ("Glass", "LAr"):black_surface, # ("Glass", "STEEL_STAINLESS_Fe7Cr2Ni"):black_surface, # ("Glass","Vacuum"):black_surface, } boundary_surfaces = { ("STEEL_STAINLESS_Fe7Cr2Ni", "LAr"): steel_surface, ("Titanium", "LAr"): titanium_surface, ("Acrylic", "LAr"): acrylic_surface, ("G10", "LAr"): g10_surface, ("Glass", "LAr"): glass_surface, ("Glass", "STEEL_STAINLESS_Fe7Cr2Ni"): steel_surface, ("Glass", "Vacuum"): black_surface, } return boundary_surfaces
import numpy as np from chroma.geometry import Material, Surface from chroma.demo.optics import vacuum, r7081hqe_photocathode import math glass = Material('glass') glass.set('refractive_index', 1.49) glass.absorption_length = \ np.array([(200, 0.1e-6), (300, 1000), (330, 1000.0), (500, 2000.0), (600, 1000.0), (770, 500.0), (800, 0.1e-6)]) glass.set('scattering_length', 1e6) silica = np.array([(180, .9), (200, .93), (220,.94), (240, .95), (260, .95), (280, .95), (800,.95)]) gel = np.array([(180, 0.0), (260, 0.0),(280, .09),(300.,.4), (320, .83), (365,.98), (404.7,0.99), (480,1.0), (800,1.0)]) mirror = np.array([(180, 0), (220, 0), (240,.0), (260, .1), (280, .4), (300, .7), (340,.88), (360, .95), (400, .97), (550, .97), (600, .95), (700, .92), (800, .87)]) mcp_boro_photocathode = Surface('mcp_boro_photocathode') mcp_silica_photocathode = Surface('mcp_silica_photocathode') ''' mcp_boro_photocathode.detect = \ np.array([(240.0, 0.00), (250.0, 0.04), (260.0, 2), (270.0, 8.77), (280.0, 24), (290.0, 26), (300.0, 27), (310.0, 28.00), (320.0, 28.8), (330.0, 29.7), (340.0, 30.1), (350.0, 30.52), (360.0, 31.0), (370.0, 31.30), (380.0, 31.20), (390.0, 31.00), (400.0, 30.90), (410.0, 30.50), (420.0, 30.16), (430.0, 29.24), (440.0, 28.31), (450.0, 27.41), (460.0, 26.25), (470.0, 24.90), (480.0, 23.05), (490.0, 21.58), (500.0, 19.94), (510.0, 18.48), (520.0, 17.01), (530.0, 15.34), (540.0, 12.93), (550.0, 10.17), (560.0, 7.86), (570.0, 6.23), (580.0, 5.07), (590.0, 4.03), (600.0, 3.18), (610.0, 2.38), (620.0, 1.72), (630.0, 0.95), (640.0, 0.71), (650.0, 0.44), (660.0, 0.25),
Transmission = [] for ii,angle in enumerate(Angles): reflect = np.tile(Refl[ii], len(chroma.geometry.standard_wavelengths)) reflect = np.array(list(zip(chroma.geometry.standard_wavelengths, reflect)), dtype=np.float32) Reflection.append(reflect) transmit = np.tile(Transm[ii], len(chroma.geometry.standard_wavelengths)) transmit = np.array(list(zip(chroma.geometry.standard_wavelengths, transmit)), dtype=np.float32) Transmission.append(transmit) angledep = chroma.geometry.DichroicProps(Angles, Reflection, Transmission) Surface.dichroic_props = angledep return Surface # fulldetect.set('reflect_diffuse', ApplyReflectivityData(fulldetect)) # fulldetect.set('reflect_specular', ApplyReflectivityData(fulldetect)) reflective = Surface('reflective') refl = angledep('reflective') reflective = refl.SetSurface('reflective') #fulldetect.set('detect', 1) sipm = Surface('sipm') sipm.set('detect', 1) #FullAbsorb surface for sipm fullAbsorb = Surface('fullAbsorb') fullAbsorb.set('absorb', 1.0) fullAbsorb.set('eta', 1) #*************************************************************************** CuSurface = Surface('CuSurface') # tailored to the real parameters of copper at this temperature/wavelength light CuSurface.cuAbsorption = 0.95 #the most likely value is 35.8% ref for copper. Source: #cu absorp-0.95 CuSurface.cuSpecReflect =0.05 #refractiveindex.info/?shelf=main&book=Cu&page=Werner #originally 0.5, CuSurface.cuSpecReflect = rp.CuSpecRef #0.05 CuSurface.cuDiffuseReflect= 0
def make_acrylic_surface_detectmode(): """ this version of acrylic surface detects photons and acts as our counting unit. """ acrylic_surface = Surface("acrylic_surface_detector") acrylic_surface.set('reflect_diffuse', 0.0) acrylic_surface.set('reflect_specular', 0.0) acrylic_surface.set('detect', 1.0) acrylic_surface.set('absorb', 0.0) acrylic_surface.set('reemit', 0.0) acrylic_surface.transmissive = 0 return acrylic_surface
def make_opticalsurface(self, dsurf, debug=False): """ :param dsurf: G4DAE surface :return: Chroma surface * name * model ? defaults to 0 G4DAE Optical Surface properties * REFLECTIVITY (the only property to be widely defined) * RINDEX (seems odd for a surface, looks to always be zero) * SPECULARLOBECONSTANT (set to 0.85 for a few surface) * BACKSCATTERCONSTANT,SPECULARSPIKECONSTANT (often present, always zero) `chroma/geometry_types.h`:: enum { SURFACE_DEFAULT, SURFACE_COMPLEX, SURFACE_WLS }; Potentially wavelength dependent props all default to zero. Having values for these is necessary to get SURFACE_DETECT, SURFACE_ABSORB * detect * absorb * reflect_diffuse * reflect_specular * reemit * eta * k * reemission_cdf `chroma/cuda/photon.h`:: 701 __device__ int 702 propagate_at_surface(Photon &p, State &s, curandState &rng, Geometry *geometry, 703 bool use_weights=false) 704 { 705 Surface *surface = geometry->surfaces[s.surface_index]; 706 707 if (surface->model == SURFACE_COMPLEX) 708 return propagate_complex(p, s, rng, surface, use_weights); 709 else if (surface->model == SURFACE_WLS) 710 return propagate_at_wls(p, s, rng, surface, use_weights); 711 else 712 { 713 // use default surface model: do a combination of specular and 714 // diffuse reflection, detection, and absorption based on relative 715 // probabilties 716 717 // since the surface properties are interpolated linearly, we are 718 // guaranteed that they still sum to 1.0. 719 float detect = interp_property(surface, p.wavelength, surface->detect); 720 float absorb = interp_property(surface, p.wavelength, surface->absorb); 721 float reflect_diffuse = interp_property(surface, p.wavelength, surface->reflect_diffuse); 722 float reflect_specular = interp_property(surface, p.wavelength, surface->reflect_specular); 723 """ if debug: print "%-75s %s " % (dsurf.name, dsurf) surface = Surface(dsurf.name) finish_map = { OpticalSurfaceFinish.polished: 'reflect_specular', OpticalSurfaceFinish.ground: 'reflect_diffuse', } if 'EFFICIENCY' in dsurf.properties: EFFICIENCY = dsurf.properties.get('EFFICIENCY', None) surface.set('detect', EFFICIENCY[:, 1], wavelengths=EFFICIENCY[:, 0]) pass elif 'REFLECTIVITY' in dsurf.properties: REFLECTIVITY = dsurf.properties.get('REFLECTIVITY', None) key = finish_map.get(int(dsurf.finish), None) if key is None or REFLECTIVITY is None: log.warn( "miss REFLECTIVITY key : not setting REFLECTIVITY for %s " % surface.name) else: log.debug("setting prop %s for surface %s " % (key, surface.name)) surface.set(key, REFLECTIVITY[:, 1], wavelengths=REFLECTIVITY[:, 0]) pass else: log.warn(" no REFLECTIVITY/EFFICIENCY in dsurf.properties %s " % repr(dsurf.properties)) pass return surface
def make_acrylic_surface_wlsmode(): """ this version of acrylic surface wavelength shifts reemitted light """ acrylic_surface = Surface("acrylic_surface_detector") acrylic_surface.set('reflect_diffuse', 0.0) acrylic_surface.set('reflect_specular', 0.0) acrylic_surface.set('detect', 0.0) acrylic_surface.set('absorb', 0.0) acrylic_surface.set( 'reemit', datatools.load_hist_data( os.path.dirname(__file__) + "/raw_tpb_emission.dat", 350, 640) ) # 100% reemission. Actually, should be 120%!! Need to think about this. acrylic_surface.transmissive = 1 return acrylic_surface
eventid = IntCol() id = IntCol() NTDC = IntCol() NS_PER_TDC = FloatCol() adc = FloatArrayCol(GPUDaqUBooNE.NTDC) q = FloatCol() t = FloatCol() class OpMap(TreeModel): opid = IntCol() x = FloatCol() y = FloatCol() z = FloatCol() lar1nd_wireplane = Surface('lar1nd_wireplane') lar1nd_wireplane.nplanes = 3.0 lar1nd_wireplane.wire_pitch = 0.3 lar1nd_wireplane.wire_diameter = 0.015 lar1nd_wireplane.transmissive = 1 lar1nd_wireplane.model = Surface.SURFACE_WIREPLANE def add_wireplane_surface(solid): # function detector class will use to add a wireplane surface to the geometry # LAr1ND has two drift regions, so we need two planes # set surface for triangles on x=-2023.25 and x=2023.25 planes for n, triangle in enumerate(solid.mesh.triangles): #print [ solid.mesh.vertices[x] for x in triangle ] # for debug nxplane = 0
def make_G10_surface(): g10_surface = Surface("g10_surface") g10_surface.set('reflect_diffuse', 0.5) g10_surface.set('reflect_specular', 0.0) g10_surface.set('detect', 0.0) g10_surface.set('absorb', 0.5) g10_surface.set('reemit', 0.0) g10_surface.transmissive = 0 return g10_surface
def testBulkReemission(self): '''Test bulk reemission Start a bunch of monoenergetic photons at the center of a wavelength- shifting sphere, forcing reemission, and check that the final wavelength distribution matches the wls spectrum. ''' import scipy.stats nphotons = 1e5 # set up detector -- a sphere of 'scintillator' surrounded by a # detecting sphere scint = Material('scint') scint.set('refractive_index', 1) scint.set('absorption_length', 1.0) scint.set('scattering_length', 1e7) scint.set('reemission_prob', 1) x = np.arange(0,1000,10) norm = scipy.stats.norm(scale=50, loc=600) pdf = 10 * norm.pdf(x) cdf = norm.cdf(x) scint.reemission_cdf = np.array(zip(x, cdf)) detector = Surface('detector') detector.set('detect', 1) world = Geometry(vacuum) world.add_solid(Solid(sphere(1000), vacuum, vacuum, surface=detector)) world.add_solid(Solid(sphere(500), scint, vacuum)) w = create_geometry_from_obj(world, update_bvh_cache=False) sim = Simulation(w, geant4_processes=0) # initial photons -- isotropic 250 nm at the origin pos = np.tile([0,0,0], (nphotons,1)).astype(np.float32) dir = np.random.rand(nphotons, 3).astype(np.float32) * 2 - 1 dir /= np.sqrt(dir[:,0]**2 + dir[:,1]**2 + dir[:,2]**2)[:,np.newaxis] pol = np.zeros_like(pos) t = np.zeros(nphotons, dtype=np.float32) wavelengths = np.ones(nphotons).astype(np.float32) * 250 photons = Photons(pos=pos, dir=dir, pol=pol, t=t, wavelengths=wavelengths) # run simulation and extract final wavelengths event = sim.simulate([photons], keep_photons_end=True).next() mask = (event.photons_end.flags & SURFACE_DETECT) > 0 final_wavelengths = event.photons_end.wavelengths[mask] # compare wavelength distribution to scintillator's reemission pdf hist, edges = np.histogram(final_wavelengths, bins=x) print 'detected', hist.sum(), 'of', nphotons, 'photons' hist_norm = 1.0 * hist / (1.0 * hist.sum() / 1000) pdf /= (1.0 * pdf.sum() / 1000) chi2 = scipy.stats.chisquare(hist_norm, pdf[:-1])[1] print 'chi2 =', chi2 # show histogram comparison #plt.figure(1) #width = edges[1] - edges[0] #plt.bar(left=edges, height=pdf, width=width, color='red') #plt.bar(left=edges[:-1], height=hist_norm, width=width) #plt.show() self.assertTrue(chi2 > 0.75)
import os, sys from chroma.importgeo import UserVG4DEAGeo, load_hist_data from chroma.geometry import Surface import numpy as np wireplane = Surface('wireplane') wireplane.nplanes = 3.0 wireplane.wire_pitch = 0.3 wireplane.wire_diameter = 0.015 wireplane.transmissive = 1 wireplane.model = Surface.SURFACE_WIREPLANE class SBND(UserVG4DEAGeo): def __init__(self): super(SBND, self).__init__("SBND", "dae/lar1nd_lightguides_nowires_chroma.dae") def surfacesdict(self): # Steel/LAr steel_surface = Surface("steel_surface") steel_surface.set('reflect_diffuse', 0.25) steel_surface.set('reflect_specular', 0.0) steel_surface.set('detect', 0.0) steel_surface.set('absorb', 0.75) steel_surface.set('reemit', 0.0) steel_surface.transmissive = 0 # Titanium/LAr titanium_surface = Surface("titanium_surface") titanium_surface.set('reflect_diffuse', 0.125)