Exemple #1
0
def build_pd(size, glass_thickness):
    """Returns a simple photodetector Solid. The photodetector is a cube of
    size `size` constructed out of a glass envelope with a photosensitive
    face on the inside of the glass envelope facing up."""
    # outside of the glass envelope
    outside_mesh = make.cube(size)
    # inside of the glass envelope
    inside_mesh = make.cube(size - glass_thickness * 2)

    # outside solid with water on the outside, and glass on the inside
    outside_solid = Solid(outside_mesh, glass, water)

    # now we need to determine the triangles which make up
    # the top face of the inside mesh, because we are going to place
    # the photosensitive surface on these triangles
    # do this by seeing which triangle centers are at the maximum z
    # coordinate
    z = inside_mesh.get_triangle_centers()[:, 2]
    top = z == max(z)

    # see np.where() documentation
    # Here we make the photosensitive surface along the top face of the inside
    # mesh. The rest of the inside mesh is perfectly absorbing.
    inside_surface = np.where(top, r7081hqe_photocathode, black_surface)
    inside_color = np.where(top, 0x00ff00, 0x33ffffff)

    # construct the inside solid
    inside_solid = Solid(inside_mesh,
                         vacuum,
                         glass,
                         surface=inside_surface,
                         color=inside_color)

    # you can add solids and meshes!
    return outside_solid + inside_solid
Exemple #2
0
    def setUp(self):
        self.cache_dir = random_tempdir('chroma_cache_test')
        self.cache = Cache(self.cache_dir)

        self.a = Geometry()
        self.a.add_solid(Solid(box(1, 1, 1)))
        self.a.add_solid(Solid(box(1, 1, 1)), displacement=(10, 10, 10))
        self.a.flatten()

        self.b = Geometry()
        self.b.add_solid(Solid(box(2, 2, 2)))
        self.b.add_solid(Solid(box(2, 2, 2)), displacement=(10, 10, 10))
        self.b.add_solid(Solid(box(2, 2, 2)), displacement=(-10, -10, -10))
        self.b.flatten()
Exemple #3
0
    def render_particle_track(self):
        x = 10.0
        h = x * np.sqrt(3) / 2
        pyramid = make.linear_extrude([-x / 2, 0, x / 2],
                                      [-h / 2, h / 2, -h / 2], h, [0] * 3,
                                      [0] * 3)
        marker = Solid(pyramid, vacuum, vacuum)

        if self.photon_display_mode == 'beg':
            photons = self.ev.photons_beg
        else:
            photons = self.ev.photons_end

        geometry = Geometry()
        sample_factor = max(1, len(photons.pos) / 10000)
        for pos in photons.pos[::sample_factor]:
            geometry.add_solid(marker,
                               displacement=pos,
                               rotation=make_rotation_matrix(
                                   np.random.uniform(0, 2 * np.pi),
                                   uniform_sphere()))

        geometry = create_geometry_from_obj(geometry)
        gpu_geometry = gpu.GPUGeometry(geometry)

        self.gpu_geometries = [self.gpu_geometry, gpu_geometry]
Exemple #4
0
 def render_photon_track(self,geometry,photon_track,sz=1.0,color='wavelength'):
     origin = photon_track.pos[:-1]
     extent = photon_track.pos[1:]-photon_track.pos[:-1]
     perp1 = np.cross(origin,extent)
     perp1 = np.inner(sz/2.0/np.linalg.norm(perp1,axis=1),perp1.T).T
     perp2 = np.cross(perp1,extent)
     perp2 = np.inner(sz/2.0/np.linalg.norm(perp2,axis=1),perp2.T).T
     verts = [perp1+perp2,-perp1+perp2,perp1-perp2,-perp1-perp2]
     bot = [vert+origin for vert in verts]
     top = [vert+origin+extent for vert in verts]
     vertices = [origin,origin+extent,bot[0],top[0],bot[1],top[1],bot[2],top[2],bot[3],top[3]]
     vertices = np.transpose(np.asarray(vertices,np.float32),(1,0,2))
     triangles = np.asarray([[1, 3, 5], [1, 5, 7], [1, 7, 9], [1, 9, 3], [3, 2, 4], [5, 4, 6], [7, 6, 8], [9, 8, 2], [2, 0, 0], [4, 0, 0], [6, 0, 0], [8, 0, 0],
                             [1, 5, 1], [1, 7, 1], [1, 9, 1], [1, 3, 1], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 2, 3], [2, 0, 4], [4, 0, 6], [6, 0, 8], [8, 0, 2]],
                             dtype=np.int32)
     if color == 'wavelength':
         r = np.asarray(np.interp(photon_track.wavelengths[:-1],[300,550,800],[0,0,255]),dtype=np.uint32)
         g = np.asarray(np.interp(photon_track.wavelengths[:-1],[300,550,800],[0,255,0]),dtype=np.uint32)
         b = np.asarray(np.interp(photon_track.wavelengths[:-1],[300,550,800],[255,0,0]),dtype=np.uint32)
         colors = np.bitwise_or(b,np.bitwise_or(np.left_shift(g,8),np.left_shift(r,16)))
     else:
         r,g,b = color
         colors = np.full_like(photon_track.wavelengths[:-1],((r<<16)|(g<<8)|b),dtype=np.uint32)
     markers = [Solid(Mesh(v,triangles), vacuum, vacuum, color=c) for v,c in zip(vertices,colors)]
     [geometry.add_solid(marker) for marker in markers]
Exemple #5
0
def build_detector():
    """Returns a cubic detector made of cubic photodetectors."""
    g = Geometry(water)
    for pos, dir in iter_box(nx, ny, nz, spacing):
        # convert to arrays
        pos, dir = np.array(pos), np.array(dir)

        # we need to figure out what rotation matrix to apply to each
        # photodetector so that the photosensitive surface will be facing
        # `dir`.
        if tuple(dir) == (0, 0, 1):
            rotation = None
        elif tuple(dir) == (0, 0, -1):
            rotation = make_rotation_matrix(np.pi, (1, 0, 0))
        else:
            rotation = make_rotation_matrix(np.arccos(dir.dot((0, 0, 1))),
                                            np.cross(dir, (0, 0, 1)))
        # add the photodetector
        g.add_solid(build_pd(size, glass_thickness),
                    rotation=rotation,
                    displacement=pos)

    world = Solid(make.box(spacing * nx, spacing * ny, spacing * nz),
                  water,
                  vacuum,
                  color=0x33ffffff)
    g.add_solid(world)

    return g
Exemple #6
0
def create_geometry_from_obj(obj,
                             bvh_name="default",
                             auto_build_bvh=True,
                             read_bvh_cache=True,
                             update_bvh_cache=True,
                             cache_dir=None,
                             cuda_device=None):
    if callable(obj):
        obj = obj()

    if isinstance(obj, Detector):
        geometry = obj
    if isinstance(obj, Geometry):
        geometry = obj
    elif isinstance(obj, Solid):
        geometry = Geometry()
        geometry.add_solid(obj)
    elif isinstance(obj, Mesh):
        geometry = Geometry()
        geometry.add_solid(Solid(obj, vacuum, vacuum, color=0x33ffffff))
    else:
        raise TypeError('cannot build type %s' % type(obj))

    geometry.flatten()

    if geometry.bvh is None:
        geometry.bvh = load_bvh(geometry,
                                auto_build_bvh=auto_build_bvh,
                                read_bvh_cache=read_bvh_cache,
                                update_bvh_cache=update_bvh_cache,
                                cache_dir=cache_dir,
                                cuda_device=cuda_device)

    return geometry
Exemple #7
0
def detector(pmt_radius=14000.0, sphere_radius=14500.0, spiral_step=350.0):
    pmt = build_8inch_pmt_with_lc()
    geo = Detector(water)

    geo.add_solid(Solid(sphere(sphere_radius,nsteps=200), 
                        water, water, 
                        surface=black_surface,
                        color=0xBBFFFFFF))

    for position in spherical_spiral(pmt_radius, spiral_step):
        direction = -normalize(position)

        # Orient PMT that starts facing Y axis
        y_axis = np.array((0.0,1.0,0.0))
        axis = np.cross(direction, y_axis)
        angle = np.arccos(np.dot(y_axis, direction))
        rotation = make_rotation_matrix(angle, axis)

        # Place PMT (note that position is front face of PMT)
        geo.add_pmt(pmt, rotation, position)
        
    
    time_rms = 1.5 # ns
    charge_mean = 1.0
    charge_rms = 0.1 # Don't I wish!
    
    geo.set_time_dist_gaussian(time_rms, -5 * time_rms, 5*time_rms)
    geo.set_charge_dist_gaussian(charge_mean, charge_rms, 0.0, charge_mean + 5*charge_rms)

    logger.info('Demo detector: %d PMTs' % geo.num_channels())
    logger.info('               %1.1f ns time RMS' % time_rms)
    logger.info('               %1.1f%% charge RMS' % (100.0*charge_rms/charge_mean))
    return geo
Exemple #8
0
def build_pmt(filename,
              glass_thickness,
              outer_material,
              glass,
              vacuum,
              photocathode_surface,
              back_surface,
              nsteps=16):
    profile = read_csv(filename)

    # slice profile in half
    profile = profile[profile[:, 0] < 0]
    profile[:, 0] = -profile[:, 0]
    # order profile from base to face
    profile = profile[np.argsort(profile[:, 1])]
    # set x coordinate to 0.0 for first and last profile along the profile
    # so that the mesh is closed
    profile[0, 0] = 0.0
    profile[-1, 0] = 0.0

    offset_profile = offset(profile, -glass_thickness)

    outer_envelope_mesh = rotate_extrude(profile[:, 0], profile[:, 1], nsteps)
    inner_envelope_mesh = rotate_extrude(offset_profile[:, 0],
                                         offset_profile[:, 1], nsteps)

    outer_envelope = Solid(outer_envelope_mesh, glass, outer_material)

    photocathode = np.mean(inner_envelope_mesh.assemble(), axis=1)[:, 1] > 0

    inner_envelope = Solid(inner_envelope_mesh,
                           vacuum,
                           glass,
                           surface=np.where(photocathode, photocathode_surface,
                                            back_surface),
                           color=np.where(photocathode, 0xff00, 0xff0000))

    pmt = outer_envelope + inner_envelope

    # profile points, outer_material, and theta are used to construct the
    # light collector
    pmt.profile = profile
    pmt.outer_material = outer_material
    pmt.nsteps = nsteps

    return pmt
Exemple #9
0
def build_light_collector_from_file(filename,
                                    outer_material,
                                    surface,
                                    nsteps=48):
    profile = read_csv(filename)

    mesh = rotate_extrude(profile[:, 0], profile[:, 1], nsteps)
    solid = Solid(mesh, outer_material, outer_material, surface=surface)
    return solid
    def testAbort(self):
        '''Photons that hit a triangle at normal incidence should not abort.

        Photons that hit a triangle at exactly normal incidence can sometimes
        produce a dot product that is outside the range allowed by acos().
        Trigger these with axis aligned photons in a box.
        '''

        # Setup geometry
        cube = Geometry(vacuum)
        cube.add_solid(Solid(box(100, 100, 100), vacuum, vacuum))
        geo = create_geometry_from_obj(cube, update_bvh_cache=False)

        # Initialize simulation (without geant4)
        sim = Simulation(geo, geant4_processes=0)

        # Create initial photons
        nphotons = 5
        pos = np.tile([0, 0, 0], (nphotons, 1)).astype(np.float32)
        dir = np.tile([0, 0, 1], (nphotons, 1)).astype(np.float32)
        pol = np.zeros_like(pos)
        phi = np.random.uniform(0, 2 * np.pi, nphotons).astype(np.float32)
        pol[:, 0] = np.cos(phi)
        pol[:, 1] = np.sin(phi)
        t = np.zeros(nphotons, dtype=np.float32)
        wavelengths = np.empty(nphotons, np.float32)
        wavelengths.fill(400.0)

        photons = Photons(pos=pos,
                          dir=dir,
                          pol=pol,
                          t=t,
                          wavelengths=wavelengths)

        # First make one step to check for strangeness
        photons_end = sim.simulate([photons],
                                   keep_photons_end=True,
                                   max_steps=1).next().photons_end
        print "FIRST STEP"
        print photons_end.pos[0:10]

        self.assertFalse(np.isnan(photons_end.pos).any())
        self.assertFalse(np.isnan(photons_end.dir).any())
        self.assertFalse(np.isnan(photons_end.pol).any())
        self.assertFalse(np.isnan(photons_end.t).any())
        self.assertFalse(np.isnan(photons_end.wavelengths).any())

        # Now let it run the usual ten steps
        photons_end = sim.simulate([photons],
                                   keep_photons_end=True,
                                   max_steps=10).next().photons_end
        aborted = (photons_end.flags & (1 << 31)) > 0
        print 'aborted photon fracttion: %1.1f' % (
            float(count_nonzero(aborted)) / nphotons)
        self.assertFalse(aborted.any())
        print "LAST STEPS"
        print photons_end.pos[0:10]
Exemple #11
0
def bvh_mesh(geometry, layer):
    lower_bounds, upper_bounds = geometry.bvh.get_layer(layer).get_bounds()

    if len(lower_bounds) == 0 or len(upper_bounds) == 0:
        raise Exception('no nodes at layer %i' % layer)

    dx, dy, dz = upper_bounds[0] - lower_bounds[0]
    center = np.mean([upper_bounds[0],lower_bounds[0]], axis=0)

    geometry = Geometry()
    
    geometry.add_solid(Solid(make.box(dx,dy,dz,center), vacuum, vacuum, color=0x33ffffff))

    for center, dx, dy, dz in list(zip(np.mean([lower_bounds,upper_bounds],axis=0),
                                  *list(zip(*upper_bounds-lower_bounds))))[1:]:
        geometry.add_solid(Solid(make.box(dx,dy,dz,center), vacuum, vacuum, color=0x33ffffff))
    
    return create_geometry_from_obj(geometry)
Exemple #12
0
 def build_detector(self, detector=None, volume_classifier=_default_volume_classifier):
     '''
     Add the meshes defined by this GDML to the detector. If detector is not
     specified, a new detector will be created.
     
     The volume_classifier should be a function that returns a classification
     of the volume ('pmt','solid','omit') and kwargs passed to the Solid
     constructor for that volume: material1, material2, color, surface
     
     The different classifications have different behaviors:
     'pmt' should specify channel_type in the kwargs to identify the channel, calls add_pmt
     'solid' will add a normal solid to the Chroma geometry, calls add_solid
     'omit' will not add the Solid to the Chroma geometry
     '''
     if detector is None:
         detector = Detector(vacuum)
     q = deque()
     q.append([self.world, np.zeros(3), np.identity(3), None])
     while len(q):
         v, pos, rot, parent_material_ref = q.pop()
         for child, c_pos, c_rot in zip(v.children, v.child_pos, v.child_rot):
             c_pos = self.get_vals(c_pos) if c_pos is not None else np.zeros(3)
             c_rot = self.get_vals(c_rot) if c_rot is not None else np.identity(3)
             c_pos = np.matmul(c_pos,rot)+pos
             x_rot = make_rotation_matrix(c_rot[0], [1, 0, 0])
             y_rot = make_rotation_matrix(c_rot[1], [0, 1, 0])
             z_rot = make_rotation_matrix(c_rot[2], [0, 0, 1])
             c_rot = np.matmul(rot, np.matmul(x_rot, np.matmul(y_rot, z_rot))) #FIXME verify this order
             q.append([child, c_pos, c_rot, v.material_ref])
         m = self.get_mesh(v.solid_ref)
         mesh = Mesh(m.vertices, m.faces) # convert PyMesh mesh to Chroma mesh
         classification, kwargs = volume_classifier(v.name, v.material_ref, parent_material_ref)
         if classification == 'pmt':
             channel_type = kwargs.pop('channel_type',None)
             solid = Solid(mesh, **kwargs)
             detector.add_pmt(solid, displacement=pos, rotation=rot, channel_type=channel_type)   
         elif classification == 'solid':
             solid = Solid(mesh, **kwargs)
             detector.add_solid(solid, displacement=pos, rotation=rot)   
         elif classification == 'omit':
             pass
         else:
             raise Exception('Unknown volume classification: '+classification)
     return detector
Exemple #13
0
    def render_photons(self,geometry,photons):
        x = 10.0
        h = x*np.sqrt(3)/2
        pyramid = make.linear_extrude([-x/2,0,x/2], [-h/2,h/2,-h/2], h,
                                      [0]*3, [0]*3)
        marker = Solid(pyramid, vacuum, vacuum)
                

        sample_factor = 1
        subset = photons[::sample_factor]
        for p,d,w in zip(subset.pos,subset.dir,subset.wavelengths):
            geometry.add_solid(marker, displacement=p, rotation=gen_rot([0,1,0],d))
Exemple #14
0
def build_kabamland(kabamland, configname):
    # focal_length sets dist between lens plane and PMT plane (or back of curved detecting surface);
    #(need not equal true lens focal length)
    config = detectorconfig.configdict(configname)

    _, lens = kb.get_lens_triangle_centers(
        config.edge_length,
        config.base,
        config.diameter_ratio,
        config.thickness_ratio,
        config.half_EPD,
        config.blockers,
        blocker_thickness_ratio=config.blocker_thickness_ratio,
        light_confinement=config.light_confinement,
        focal_length=config.focal_length,
        lens_system_name=config.lens_system_name)
    surf = mh.rotate(
        kb.curved_surface2(config.detector_r,
                           diameter=2 *
                           kb.find_max_radius(config.edge_length, config.base),
                           nsteps=9),
        make_rotation_matrix(-np.pi / 2, (1, 0, 0)))
    surf = mh.shift(surf, (0, 0, -config.focal_length))
    kabamland.add_solid(Solid(surf, lm.ls, lm.ls, lm.fulldetect, 0x0000FF),
                        rotation=None,
                        displacement=(0, 0, 0))
    kabamland.add_solid(Solid(lens, lm.lensmat, lm.ls),
                        rotation=None,
                        displacement=None)

    blocker = BuildBlocker(
        np.max(lens.assemble()[:, :, 0].flatten()),
        lens.assemble()[:, :,
                        2].flatten()[np.argmax(lens.assemble()[:, :,
                                                               0].flatten())])
    kabamland.add_solid(Solid(blocker, lm.ls, lm.ls, lm.fullabsorb, 0x0000FF),
                        rotation=None,
                        displacement=(0, 0, 0))
    kabamland.channel_index_to_channel_id = [1]
    return lens, surf
Exemple #15
0
    def setUp(self):
        self.cache_dir = random_tempdir('chroma_cache_test')
        self.cache = Cache(self.cache_dir)

        self.a = Geometry()
        self.a.add_solid(Solid(box(1, 1, 1)))
        self.a.add_solid(Solid(box(1, 1, 1)), displacement=(10, 10, 10))
        self.a.flatten()

        self.b = Geometry()
        self.b.add_solid(Solid(box(2, 2, 2)))
        self.b.add_solid(Solid(box(2, 2, 2)), displacement=(10, 10, 10))
        self.b.add_solid(Solid(box(2, 2, 2)), displacement=(-10, -10, -10))
        self.b.flatten()

        # c is not in cache
        self.c = Geometry()
        self.c.add_solid(Solid(box(2, 2, 2)))
        self.c.flatten()

        self.a_hash = self.a.mesh.md5()
        self.b_hash = self.b.mesh.md5()
        self.c_hash = self.c.mesh.md5()

        self.cache.save_geometry('a', self.a)
        self.cache.save_geometry('b', self.b)
Exemple #16
0
def build_pmt_icosahedron(kabamland, vtx, focal_length=1.0):
    offset = 1.2 * (vtx + focal_length)
    angles = np.linspace(np.pi / 4, 2 * np.pi + np.pi / 4, 4, endpoint=False)
    square = make.linear_extrude(offset * np.sqrt(2) * np.cos(angles),
                                 offset * np.sqrt(2) * np.sin(angles), 2.0)
    vrs = np.eye(3)
    for vr in vrs:
        if np.array_equal(vr, [0, 0, 1]):
            kabamland.add_pmt(Solid(square, glass, kabamland.detector_material,
                                    lm.fullabsorb, 0xBBFFFFFF),
                              displacement=offset * vr)
            kabamland.add_pmt(Solid(square, glass, kabamland.detector_material,
                                    lm.fullabsorb, 0xBBFFFFFF),
                              displacement=-offset * vr)
        else:
            trasl = np.cross(vr, [0, 0, 1])
            kabamland.add_pmt(Solid(square, glass, kabamland.detector_material,
                                    lm.fullabsorb, 0xBBFFFFFF),
                              rotation=make_rotation_matrix(np.pi / 2, vr),
                              displacement=offset * trasl)
            kabamland.add_pmt(Solid(square, glass, kabamland.detector_material,
                                    lm.fullabsorb, 0xBBFFFFFF),
                              rotation=make_rotation_matrix(np.pi / 2, vr),
                              displacement=-offset * trasl)
Exemple #17
0
    def setUp(self):
        # Setup geometry
        cube = Detector(vacuum)
        cube.add_pmt(
            Solid(box(10.0, 10, 10),
                  vacuum,
                  vacuum,
                  surface=r7081hqe_photocathode))
        cube.set_time_dist_gaussian(1.2, -6.0, 6.0)
        cube.set_charge_dist_gaussian(1.0, 0.1, 0.5, 1.5)

        geo = create_geometry_from_obj(cube, update_bvh_cache=False)

        self.geo = geo
        self.sim = Simulation(self.geo, geant4_processes=0)
Exemple #18
0
def build_pmt_shell(filename, outer_material, glass, nsteps=16):
    profile = read_csv(filename)

    # slice profile in half
    profile = profile[profile[:, 0] < 0]
    profile[:, 0] = -profile[:, 0]
    # order profile from base to face
    profile = profile[np.argsort(profile[:, 1])]
    # set x coordinate to 0.0 for first and last profile along the profile
    # so that the mesh is closed
    profile[0, 0] = 0.0
    profile[-1, 0] = 0.0

    return Solid(rotate_extrude(profile[:, 0], profile[:, 1], nsteps),
                 glass,
                 outer_material,
                 color=0xeeffffff)
Exemple #19
0
def build_light_collector(pmt, a, b, d, rmin, rmax, surface, npoints=10):
    if not isinstance(pmt, Solid):
        raise Exception('`pmt` must be an instance of %s' % Solid)

    lc_radii = np.linspace(rmin, rmax, npoints)
    lc_profile = get_lc_profile(lc_radii, a, b, d, rmin, rmax)

    pmt_face_profile = pmt.profile[pmt.profile[:, 1] > -1e-3]

    lc_offset = np.interp(lc_radii[0], list(reversed(pmt_face_profile[:, 0])),
                          list(reversed(pmt_face_profile[:, 1])))

    lc_mesh = rotate_extrude(lc_radii, lc_profile + lc_offset, pmt.nsteps)

    return Solid(lc_mesh,
                 pmt.outer_material,
                 pmt.outer_material,
                 surface=surface)
Exemple #20
0
    def setUp(self):
        self.cube = Geometry(water)
        self.cube.add_solid(Solid(box(100,100,100), water, water))
        self.geo = create_geometry_from_obj(self.cube, update_bvh_cache=False)
        self.sim = Simulation(self.geo, geant4_processes=0)

        nphotons = 100000
        pos = np.tile([0,0,0], (nphotons,1)).astype(np.float32)
        dir = np.tile([0,0,1], (nphotons,1)).astype(np.float32)
        pol = np.zeros_like(pos)
        phi = np.random.uniform(0, 2*np.pi, nphotons).astype(np.float32)
        pol[:,0] = np.cos(phi)
        pol[:,1] = np.sin(phi)
        t = np.zeros(nphotons, dtype=np.float32)
        wavelengths = np.empty(nphotons, np.float32)
        wavelengths.fill(400.0)

        self.photons = Photons(pos=pos, dir=dir, pol=pol, t=t, wavelengths=wavelengths)
Exemple #21
0
    def render_vertex(
        self,
        geometry,
        vertex,
        children=2,
        sz=5.0,
        colors={
            'mu+': 0x50E0FF,
            'mu-': 0xFFE050,
            'e+': 0x0000FF,
            'e-': 0xFF0000,
            'gamma': 0x00FF00
        }):
        steps = np.vstack((vertex.steps.x, vertex.steps.y, vertex.steps.z)).T
        for index in range(len(steps) - 1):
            vec = steps[index + 1] - steps[index]
            mag = np.linalg.norm(vec)
            u = vec / mag
            axis = np.cross(u, [0, 0, 1])
            ang = np.arccos(np.dot(u, [0, 0, 1]))
            rotmat = make_rotation_matrix(ang, axis)
            x = sz / 2
            y = x * np.sqrt(3) / 2
            segment = make.linear_extrude([-x, 0, x], [-y, y, -y], mag,
                                          [0, 0, 0], [0, 0, 0])
            segment.vertices[:, 2] += mag / 2.0
            marker = Solid(segment,
                           vacuum,
                           vacuum,
                           color=colors[vertex.particle_name]
                           if vertex.particle_name in colors else 0xAAAAAA)
            geometry.add_solid(marker,
                               displacement=steps[index],
                               rotation=rotmat)

        if children and vertex.children:
            for child in vertex.children:
                if isinstance(children, bool):
                    self.render_vertex(geometry, child, children)
                else:
                    self.render_vertex(geometry, child, children - 1)
Exemple #22
0
def build_curvedsurface_icosahedron(kabamland,
                                    vtx,
                                    rad,
                                    diameter_ratio,
                                    focal_length=1.0,
                                    detector_r=1.0,
                                    nsteps=10,
                                    b_pxl=4):
    initial_curved_surf = mh.rotate(
        curved_surface2(detector_r,
                        diameter=rad * 2,
                        nsteps=nsteps,
                        base_pxl=b_pxl),
        make_rotation_matrix(-np.pi / 2, (1, 0, 0)))
    face = Solid(initial_curved_surf, kabamland.detector_material,
                 kabamland.detector_material, lm.fulldetect, 0x0000FF)
    phi, axs = rot_axis([0, 0, 1], vtx)
    for vx, ph, ax in zip(vtx, -phi, axs):
        kabamland.add_solid(face,
                            rotation=make_rotation_matrix(ph, ax),
                            displacement=-normalize(vx) *
                            (np.linalg.norm(vx) + focal_length))
Exemple #23
0
    def setUp(self):
        # Setup geometry
        cube = Detector(vacuum)
        cube.add_pmt(
            Solid(box(10.0, 10.0, 10.0),
                  vacuum,
                  vacuum,
                  surface=r7081hqe_photocathode))
        cube.set_time_dist_gaussian(1.2, -6.0, 6.0)
        cube.set_charge_dist_gaussian(1.0, 0.1, 0.5, 1.5)

        geo = create_geometry_from_obj(cube,
                                       update_bvh_cache=True,
                                       read_bvh_cache=False)
        print "Number of channels in detector: ", geo.num_channels()
        self.geo = geo
        self.sim = Simulation(self.geo,
                              geant4_processes=0,
                              nthreads_per_block=1,
                              max_blocks=1)

        self.rfile = rt.TFile("output_test_detector.root", "recreate")
        self.htime = rt.TH1D("htime", "Time;ns", 120, 80, 120)
        self.hcharge = rt.TH1D("hcharge", "Charge;pe", 100, 0.5, 1.5)
Exemple #24
0
    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)
Exemple #25
0
def main(suppress=False):
    
    ##### Loading in Results #####
    print '-'*90
    print 'ANALYSIS SCRIPT FOR VUV SIMULATION'.center(90,'=')
    print '-'*90
    print 'Available files:\n'
    filenames = []
    display = ['#','Date:','Time:','n:',u'\u03bb (nm)'.encode('utf-8'),u'd (\u03bcm)'.encode('utf-8'),u's (\u03bcm)'.encode('utf-8')]
    print '{:<3}{:<12}{:<9}{:<9}{:<9}{:<9}{:<9}'.format(*display)
 
    for pos,filename in enumerate(os.listdir('results/')):
        filenames.append(filename)
        date = re.findall('\d+\-\d+\-\d+',filename)[0]
        time = re.findall('\d{2}\:\d{2}',filename)[0]
        args = re.findall('\d+\:\d+:\d+\.\d+\:\d+\.\d+',filename)[0]
        display = [str(pos),date,time] + args.split(':')
        print '{:<3}{:<12}{:<9}{:<9}{:<8}{:<8}{:<9}'.format(*display)
    print '(d - Slit Width, s - Beam Width)'
    print '='*90

    proceed = False
    while proceed == False:
        usrin = raw_input('Please select a file: ').strip()
        if usrin not in [str(i) for i in list(range(len(filenames)))]:
            print 'Bad input!'
        else:
            proceed = True

    selection = filenames[int(usrin)] 
    n,wavelength,width,beamsize = [float(i) for i in re.findall('\d+\:\d+:\d+\.\d+\:\d+\.\d+',selection)[0].split(':')]

    #print '\nSelected: '+ selection + '\n'

    ##### Data Loading and Results #####

    itm = 25.4 #Inches to millimetre conversion
    tol = 0.05  #Tolerance for selecting photons 
    res = 10 #Seed resolution
    seed = np.genfromtxt('config/seed.dat',delimiter=',') #display seed

    x = 0.01    #marker params
    h = x*np.sqrt(3)/2
    pyramid = make.linear_extrude([-x/2,0,x/2],[-h/2,h/2,-h/2],h,[0]*3,[0]*3)

    beg_marker = Solid(pyramid,vacuum,vacuum,color=0x32a8a2)    #photon start marker
    end_marker = Solid(pyramid,vacuum,vacuum,color=0xfc0303)    #photon end marker
    dir_marker = Solid(pyramid,vacuum,vacuum,color=0x00ff00) #Direction

    data = p.read_csv('results/'+selection,sep = '\t').values[:]
    
    photon_ids = data[:,0].astype(int)
    beg_pos = data[:,1:4]
    end_pos = data[:,4:7]
    wavelengths = data[:,7].astype(int)
    flags = data[:,8].astype(int)

    if suppress == False:
        if os.path.exists('config/geometry.pickle'):
            print 'Loading geometry from file...'
            geometry_path = open('config/geometry.pickle','rb')
            world = cPickle.load(geometry_path)
            world.add_solid(dir_marker,displacement = mfunctions.get_center('161')+np.array((0,1,0)))
            geometry_path.close()
        else:
            world = builder.build()   #Regenerate geometry
   
    sipm_ids = []
    pmt_ids = []
    for p_id in photon_ids:
        if (flags[p_id] & 0x1 << 2) == 4:
            if abs(end_pos[p_id,2]-9.08933)<tol:   #Photons detected at SiPM
                sipm_ids.append(p_id)
            elif abs(end_pos[p_id,0]-23.6555999)<tol:  #Photons detected at PMT
                pmt_ids.append(p_id)
        if suppress == False and seed[p_id] <= 1.0/res:
            world.add_solid(beg_marker,displacement=beg_pos[p_id])
            world.add_solid(end_marker,displacement=end_pos[p_id])
            
    pcount = len(pmt_ids)
    scount = len(sipm_ids)
        
    print 'Total photons:\t\t', n
    print 'Detections (PMT):\t', pcount
    print 'Detections (SiPM):\t',scount
    print 'Relative detection rate: {:.2f}%'.format(100*float(scount+pcount)/len(photon_ids))
    
    if suppress == False:
        view(world)
    elif suppress == True and scount == 0:
        print 'No photons detected!'
        exit()
    else:
        detectedx = np.asarray(list(end_pos[i,0]*itm for i in sipm_ids)) #Compiling points to plot and converting to mm
        detectedy = np.asarray(list(end_pos[i,1]*itm for i in sipm_ids))
        detectedwavs = np.array(list(wavelengths[i] for i in pmt_ids))
        
        meanx = np.mean(detectedx) #Mean detected positions
        meany = np.mean(detectedy)

        detectedx -= meanx #Centering plot about detected photons
        detectedy -= meany
      
        sampleset = np.sqrt(detectedx**2 + detectedy**2) #Heatmap info        
        binwidth = 2*ss.iqr(sampleset)/np.cbrt(len(sampleset)) #Freedman-Diaconis rule
        bins = (max(sampleset)-min(sampleset))/binwidth
        heatmap,xedges,yedges = np.histogram2d(detectedx,detectedy,bins=bins)
        extent = [xedges[0],xedges[-1],yedges[0],yedges[-1]]
       
        fig = plt.figure()
        ax1 = fig.add_subplot(121)
        ax2 = fig.add_subplot(122)
        ax1.axis('equal')
        ax2.axis('equal')
        fig.suptitle(u'n: {} | \u03bb: {}nm | d: {}\u03bcm | s: {}\u03bcm'.format(int(n),int(wavelength),width,beamsize))
        
        r = 0.059813*itm #Iris radius
        theta = np.linspace(0,2*np.pi,1000)
        iris_center = np.array((18.4429,-21.8872))*itm

        iris_x = r*np.cos(theta)+iris_center[0]-meanx
        iris_y = r*np.sin(theta)+iris_center[1]-meany

        ax1.scatter(detectedx,detectedy,s=0.3,c='k',label='Photon Hits')
        #ax1.plot(iris_x,iris_y,c='r',label='Iris Overlay')
        ax1.set_xlabel('x (mm)')
        ax1.set_ylabel('y (mm)')
        ax1.set_title('SiPM Hits')
        ax1.legend()

        im = ax2.imshow(heatmap.T,extent=extent,origin='lower',cmap='hot_r',interpolation='gaussian')
        ax2.set_xlabel('x (mm)')
        ax2.set_ylabel('y (mm)')
        ax2.set_title('SiPM Heat Map')
                
        fig.colorbar(im,ax=ax2) 
        plt.show()
Exemple #26
0
def build(slit_width):
    
    
    directory = 'stls/' #directory containing individual detector .stls
    
    
    ##### Generating World #####
    print 'Generating world...'
    size = (40,40,40) #Bounds for world box
    world = Geometry(vacuum)
    bounds = Solid(make.box(*size),vacuum,vacuum,color=0x33ffffff)
    world.add_solid(bounds,displacement=(18,-18,10))

    ##### Generating Non-Special Solids #####
    print 'Generating non-special solids...'
    blacklist = mfunctions.get_blacklist()  #Mesh read-in blacklist
    tol = 0.005 #Tolerance for painting meshes using conditionals

    setup_solid = Solid(make.cube(1),vacuum,vacuum,color=0xf0fc03) #origin

    for filename in os.listdir(directory):
        path = os.path.join(directory,filename)
        tmp_mesh = mesh_from_stl(path)
        mesh_no = re.findall('\d+',path)[0] #Select mesh number
                   
        if mesh_no in ['141','142']:    #Angled mirrors
            setup_surf, setup_col = mfunctions.mirror(mesh_no)
            """
        elif mesh_no in ['161','206']:  #Slit housing
            setup_surf = shiny_surface
            setup_col = 0x7d6b56 #grey
            """
        else:   #Non-optical components
            setup_surf = black_surface
            setup_col = 0x7d6b56 #grey
        #print 'Adding solid '+mesh_no+'/249' 
        if mesh_no not in blacklist:    #Remove blacklisted meshes from setup
            setup_solid += Solid(tmp_mesh,vacuum,vacuum,surface=setup_surf,color=setup_col)

    world.add_solid(setup_solid)

    ##### Generating Special Solids #####
    print 'Generating special solids...'
    """
    #Laser Absorb
    laser_absorb = Solid(make.segmented_cylinder(1,0.1),vacuum,vacuum,surface=black_surface,color=0xffff00) 
    cap_center = np.array((18.470600,-26.771999,19.469999))
    world.add_solid(laser_absorb,displacement=cap_center)
    """
    #SiPM Plate
    sipm_plate = Solid(mesh_from_stl(directory+'vuv_setup - Mesh 188.stl'),vacuum,vacuum,surface=black_surface,color=0xfc7f03)
    rotation_matrix = mfunctions.Ry(np.arctan(0.0755832))   #Correction for SiPM plate rotation in the STL
    sipm_center = np.array((18.48695,-22.89630,9.08933)) #Centre of SiPM plate
    correction = sipm_center-np.matmul(rotation_matrix,sipm_center) #Off-centre rotation induces displacement, this corrects for this
    world.add_solid(sipm_plate,rotation=rotation_matrix,displacement=correction+np.array((0,1,0)))

    #Detector Plate/SiPM
    detector = Solid(make.box(2,3,0.01),vacuum,vacuum,surface=mfunctions.get_sipm_surface(),color=0x0dff00) 
    world.add_solid(detector,displacement=sipm_center+np.array((0,0.8,0)))

    #Closed Mirror 
    #mirror_surf,mirror_col = mfunctions.mirror('250')
    mirror_surf = mfunctions.get_mirror_surface()
    mirror_col = 0xe6ad12 
    closed_mirror = Solid(mesh_from_stl(directory+'vuv_setup - Mesh 250.stl'),vacuum,vacuum,surface=mirror_surf,color=mirror_col)
    world.add_solid(closed_mirror,rotation=mfunctions.Ry(np.pi),displacement=np.array((18.470901,-21.916050,19.602501))+np.array((0,0,0.613293)))
    
    #Post-Monochromator Slit Doors
    basex = np.array((0.0,0.0,0.074744,0.6,0.6))#x-points for door base
    basey = np.array((0.0,0.00488564,0.0800017,0.0800017,0.0))#y-points
    height = 0.65
    #Max slit width: 1000micron
    door1 = make.linear_extrude(basex,basey,height)
    door2 = make.linear_extrude(-basex,basey,height)
    slit_center = mfunctions.get_center('161')
    door1_solid = Solid(door1,vacuum,vacuum,surface=shiny_surface,color=0xffff00)
    door2_solid = Solid(door2,vacuum,vacuum,surface=shiny_surface,color=0xffff00)
    world.add_solid(door1_solid,displacement=slit_center+np.array((0.5*slit_width,-0.144076,-0.05)))
    world.add_solid(door2_solid,displacement=slit_center+np.array((-0.5*slit_width,-0.144076,-0.05)))
    
    #PMT plate
    pmt_center = mfunctions.get_center('210')
    pmt_center += np.array((0.4,0,0))
    pmt_solid = Solid(make.segmented_cylinder(1.5,0.1),vacuum,vacuum,surface=mfunctions.get_pmt_surface(),color=0x0dff00)
    world.add_solid(pmt_solid,rotation=mfunctions.Rz(np.pi/2),displacement=pmt_center)

    ##### Saving Geometry to File #####

    config_path = open('config/geometry.pickle','wb')
    cPickle.dump(world,config_path)   
    config_path.close() 
    config_path = open('config/vars.txt','wb')
    config_path.write(str(slit_width)+'\n')
    config_path.write('This is the config file for geometry.pickle.\nAltering this file will cause geometry.pickle to regenerate!')
    config_path.close()
    print 'Done.'
    
    return world
Exemple #27
0
def build_checkerboard_scene(checkers_per_side=10, squares_per_checker=50):
    x = np.linspace(-5000.0, 5000.0,
                    checkers_per_side * squares_per_checker + 1)
    y = np.linspace(-5000.0, 5000.0,
                    checkers_per_side * squares_per_checker + 1)

    vertices = np.array(tuple(product(x, y, [0])))

    triangles = []
    for j in range(y.size - 1):
        for i in range(x.size - 1):
            triangles.append([
                j * len(x) + i, (j + 1) * len(x) + i, (j + 1) * len(x) + i + 1
            ])
            triangles.append(
                [j * len(x) + i, j * len(x) + i + 1, (j + 1) * len(x) + i + 1])

    checkerboard_mesh = Mesh(vertices,
                             triangles,
                             remove_duplicate_vertices=True)

    checkerboard_color_line1 = take(
        checkers_per_side * squares_per_checker * 2,
        cycle([0] * 2 * squares_per_checker +
              [0xffffff] * 2 * squares_per_checker)) * squares_per_checker
    checkerboard_color_line2 = take(
        checkers_per_side * squares_per_checker * 2,
        cycle([0xffffff] * 2 * squares_per_checker +
              [0] * 2 * squares_per_checker)) * squares_per_checker
    checkerboard_color = take(
        len(checkerboard_mesh.triangles),
        cycle(checkerboard_color_line1 + checkerboard_color_line2))

    checkerboard_surface_line1 = take(
        checkers_per_side * squares_per_checker * 2,
        cycle([black_surface] * 2 * squares_per_checker +
              [lambertian_surface] * 2 *
              squares_per_checker)) * squares_per_checker
    checkerboard_surface_line2 = take(
        checkers_per_side * squares_per_checker * 2,
        cycle([lambertian_surface] * 2 * squares_per_checker +
              [black_surface] * 2 * squares_per_checker)) * squares_per_checker
    checkerboard_surface = take(
        len(checkerboard_mesh.triangles),
        cycle(checkerboard_surface_line1 + checkerboard_surface_line2))

    checkerboard = Solid(checkerboard_mesh,
                         vacuum,
                         vacuum,
                         surface=checkerboard_surface,
                         color=checkerboard_color)

    sphere1 = Solid(sphere(1000.0, nsteps=512), water, vacuum)
    sphere2 = Solid(sphere(1000.0, nsteps=512),
                    vacuum,
                    vacuum,
                    surface=shiny_surface)
    sphere3 = Solid(sphere(1000.0, nsteps=512),
                    vacuum,
                    vacuum,
                    surface=lambertian_surface)

    checkerboard_scene = Geometry()
    checkerboard_scene.add_solid(checkerboard, displacement=(0, 0, -1500.0))
    checkerboard_scene.add_solid(sphere1, displacement=(2000.0, -2000.0, 0))
    checkerboard_scene.add_solid(sphere2, displacement=(-2000.0, -2000.0, 0))
    checkerboard_scene.add_solid(sphere3, displacement=(0.0, 2000.0, 0))

    return checkerboard_scene
Exemple #28
0
def build_lens_icosahedron(kabamland,
                           vtx,
                           rad,
                           diameter_ratio,
                           thickness_ratio,
                           half_EPD,
                           blockers=True,
                           blocker_thickness_ratio=1.0 / 1000,
                           light_confinement=False,
                           focal_length=1.0,
                           lens_system_name=None):
    """input edge length of icosahedron 'edge_length',
       the number of small triangles in the base of each face 'base',
       the ratio of the diameter of each lens to the maximum diameter possible 'diameter_ratio' (or the fraction of the default such ratio,
       if a curved detector lens system), the ratio of the thickness of the lens to the chosen (not maximum) diameter 'thickness_ratio',
       the radius of the blocking entrance pupil 'half_EPD',
       and the ratio of the thickness of the blockers to that of the lenses 'blocker_thickness_ratio'
       to return the icosahedron of lenses in kabamland. Light_confinment=True adds cylindrical shells behind each lens that absorb all the light that touches them,
       so that light doesn't overlap between lenses. If lens_system_name is a string that matches one of the lens systems in lenssystem.py,
       the corresponding lenses and detectors will be built. Otherwise, a default simple lens will be built, with parameters hard-coded below.
    """
    # Get the list of lens meshes from the appropriate lens system as well as the lens material'''
    scale_rad = rad * diameter_ratio  #max_radius->rad of the lens assembly
    lenses = lenssystem.get_lens_mesh_list(lens_system_name, scale_rad)
    lensmat = lenssystem.get_lens_material(lens_system_name)
    face = None
    for lns in lenses:
        #lns = mh.rotate(lns,make_rotation_matrix(ph,ax))
        if not face:
            face = Solid(lns, lensmat, kabamland.detector_material)
        else:
            face += Solid(lns, lensmat, kabamland.detector_material)

    if light_confinement:
        shield = mh.rotate(
            cylindrical_shell(rad * (1 - 0.001), rad, focal_length, 32),
            make_rotation_matrix(np.pi / 2.0, (1, 0, 0)))
        baffle = Solid(shield, lensmat, kabamland.detector_material,
                       black_surface, 0xff0000)

    if blockers:
        blocker_thickness = 2 * rad * blocker_thickness_ratio
        if half_EPD < rad:
            c1 = lenssystem.get_lens_sys(
                lens_system_name).c1 * lenssystem.get_scale_factor(
                    lens_system_name, scale_rad)
            offset = [0, 0, c1 - np.sqrt(c1 * c1 - rad * rad)]
            anulus_blocker = mh.shift(
                mh.rotate(
                    cylindrical_shell(half_EPD, rad, blocker_thickness, 32),
                    make_rotation_matrix(np.pi / 2.0, (1, 0, 0))), offset)
            face += Solid(anulus_blocker, lensmat, kabamland.detector_material,
                          black_surface, 0xff0000)
    phi, axs = rot_axis([0, 0, 1], vtx)
    for vx, ph, ax in zip(vtx, -phi, axs):
        kabamland.add_solid(face,
                            rotation=make_rotation_matrix(ph, ax),
                            displacement=-vx)
        if light_confinement:
            kabamland.add_solid(baffle,
                                rotation=make_rotation_matrix(ph, ax),
                                displacement=-normalize(vx) *
                                (np.linalg.norm(vx) + focal_length / 2.0))
Exemple #29
0
    def visit(self, node, debug=False):
        """
        :param node: DAENode instance

        DAENode instances and their pycollada underpinnings meet chroma here

        Chroma needs sensitive detectors to have an associated surface 
        with detect property ...
        """
        #assert node.__class__.__name__ == 'DAENode'
        self.vcount += 1
        if self.vcount < 10:
            log.debug("visit : vcount %s node.index %s node.id %s " %
                      (self.vcount, node.index, node.id))

        bps = list(node.boundgeom.primitives())

        bpl = bps[0]

        assert len(bps) == 1 and bpl.__class__.__name__ == 'BoundPolylist'

        tris = bpl.triangleset()

        vertices = tris._vertex

        triangles = tris._vertex_index

        mesh = Mesh(vertices, triangles, remove_duplicate_vertices=False)

        material2, material1 = self.find_outer_inner_materials(node)

        surface = self.find_surface(
            node)  # lookup Chroma surface corresponding to the node
        if surface == None:
            surfacename = "NOT SPECIFIED"
        else:
            surfacename = surface.name
        if self.dump_node_info:
            print "[NODE %05d:%s]" % (
                node.index, node.lv.id
            ), " NTriangles=%d OuterMat=%s InnerMat=%s Surface=%s" % (len(
                mesh.triangles), material2.name, material1.name, surfacename)

        color = 0x33ffffff

        solid = Solid(mesh, material1, material2, surface, color)
        solid.node = node

        #
        # hmm a PMT is comprised of several volumes all of which
        # have the same associated channel_id
        #
        channel_id = getattr(node, 'channel_id', None)
        if not channel_id is None and channel_id > 0:
            self.channel_count += 1  # nodes with associated non zero channel_id
            self.channel_ids.add(channel_id)
            self.chroma_geometry.add_pmt(solid, channel_id=channel_id)
        else:
            self.chroma_geometry.add_solid(solid)
        pass

        if debug and self.vcount % 1000 == 0:
            print node.id
            print self.vcount, bpl, tris, tris.material
            print mesh
            #print mesh.assemble()
            bounds = mesh.get_bounds()
            extent = bounds[1] - bounds[0]
            print extent
Exemple #30
0
def load_geometry_from_string(geometry_str,
                              auto_build_bvh=True,
                              read_bvh_cache=True,
                              update_bvh_cache=True,
                              cache_dir=None,
                              cuda_device=None):
    '''Create or load a geometry and optionally load/build a BVH for it.

    This is a convenience interface to the geometry and BVH construction code,
    as well as the Chroma caching layer.  Most applications should use
    this function rather than manually building a Geometry and BVH.

    The geometry string passed to this function has several forms:

      "" (empty string) - Load the default geometry from the cache and
          the default BVH for that geometry.

      "filename.stl" or "filename.stl.bz2" - Create a geometry from a
          3D mesh on disk.  This model will not be cached, but the
          BVH can be, depending on whether update_bvh_cache is True.

      "geometry_name" - Load a geometry from the cache with this name
          and the default BVH for that geometry.

      "geometry_name:bvh_name" - Load a geometry from the cache and
          the requested BVH by name.
                                 
      "@chroma.models.lionsolid" - Run this function inside a Python
          module, found in the current $PYTHONPATH, to create the
          geometry, and load the default BVH.  For convenience, the
          current directory is also added to the $PYTHONPATH.

      "@chroma.models.lionsolid:bvh_name" - Run this function to
          create the Geometry and load a BVH by name.

    By default, the Chroma cache in the user's home directory is
    consulted for both the geometry and the BVH.  A different cache
    directory can be selected by passing the path in via the
    ``cache_dir`` parameter.

    If ``read_bvh_cache`` is set to False, then the BVH cache will not
    be inspected for BVH objects.

    If the requested BVH (default, or named) does not exist for this
    geometry (checked by MD5 hashing the geometry mesh) and
    ``auto_build_bvh`` is true, then a BVH will be automatically
    generated using the "simple" BVH algorithm.  The simple algorithm
    is very fast, but produces a poor quality BVH.

    Any newly created BVH will be saved in the Chroma cache if the
    ``update_cache_bvh`` parameter is True.
    
    BVH construction requires a GPU, so the CUDA device number can be
    specified with the ``cuda_device`` parameter.

    Returns: a Geometry object (or subclass) with the ``bvh`` property
      set if the options allow.
    '''
    # Find BVH id if given
    bvh_name = 'default'
    if ':' in geometry_str:
        geometry_id, bvh_name = geometry_str.split(':')
    else:
        geometry_id = geometry_str

    if cache_dir is None:
        cache = Cache()
    else:
        cache = Cache(cache_dir)

    # Where is the geometry coming from?
    if os.path.exists(geometry_id) and \
            geometry_id.lower().endswith(('.stl', '.bz2')):
        # Load from file
        mesh = mesh_from_stl(geometry_id)
        geometry = Geometry()
        geometry.add_solid(Solid(mesh, vacuum, vacuum, color=0x33ffffff))
        geometry.flatten()

    elif geometry_id.startswith('@'):
        # Load from function
        function_path = geometry_id[1:]

        module_name, obj_name = function_path.rsplit('.', 1)
        orig_sys_path = list(sys.path)
        try:
            sys.path.append('.')
            module = __import__(module_name, fromlist=[obj_name])
            sys.path = orig_sys_path
        except ImportError:
            sys.path = orig_sys_path
            raise

        obj = getattr(module, obj_name)

        geometry = create_geometry_from_obj(obj,
                                            bvh_name=bvh_name,
                                            auto_build_bvh=auto_build_bvh,
                                            read_bvh_cache=read_bvh_cache,
                                            update_bvh_cache=update_bvh_cache,
                                            cache_dir=cache_dir,
                                            cuda_device=cuda_device)
        return geometry  # RETURN EARLY HERE!  ALREADY GOT BVH

    else:
        # Load from cache
        if geometry_id == '':
            geometry = cache.load_default_geometry()
        else:
            geometry = cache.load_geometry(geometry_id)
        # Cached geometries are flattened already

    geometry.bvh = load_bvh(geometry,
                            bvh_name=bvh_name,
                            auto_build_bvh=auto_build_bvh,
                            read_bvh_cache=read_bvh_cache,
                            update_bvh_cache=update_bvh_cache,
                            cache_dir=cache_dir,
                            cuda_device=cuda_device)

    return geometry