Ejemplo n.º 1
0
class Tracer(object):
    """An object that will fire multiple photons through the scene."""
    def __init__(self, scene=None, source=None, throws=1, steps=50, seed=None, use_visualiser=True, show_log=True, background=(0.957, 0.957, 1), ambient=0.5):
        super(Tracer, self).__init__()
        self.scene = scene
        from LightSources import SimpleSource, PlanarSource, CylindricalSource, PointSource, RadialSource
        self.source = source
        self.throws = throws
        self.steps = steps
        self.totalsteps = 0
        self.seed = seed
        self.killed = 0
        self.database = PhotonDatabase.PhotonDatabase()
        self.stats = dict()
        self.show_log = show_log
        np.random.seed(self.seed)
        if not use_visualiser:
            Visualiser.VISUALISER_ON = False
        else:
            Visualiser.VISUALISER_ON = True
        self.visualiser = Visualiser(background=background, ambient=ambient)
        
        for obj in scene.objects:
            if obj != scene.bounds:
                if not isinstance(obj.shape, CSGadd) and not isinstance(obj.shape, CSGint) and not isinstance(obj.shape, CSGsub):
                
                    if isinstance(obj.material, SimpleMaterial):
                        wavelength = obj.material.bandgap
                    else:
                        
                        if not hasattr(obj.material, 'all_absorption_coefficients'):
                            maxindex = obj.material.emission_data.y.argmax()
                            wavelength = obj.material.emission_data.x[maxindex]
                            colour = wav2RGB(wavelength)
                        else:
                            # It is possible to processes the most likley colour of a spectrum in a better way than this!
                            colour = [0.1,0.1,0.1]
                        
                        if colour[0] == np.nan or colour[1] == np.nan or colour[2] == np.nan:
                            colour = [0.1,0.1,0.1]
                        
                        self.visualiser.addObject(obj.shape, colour=colour)
                        
        self.show_lines = True#False
        self.show_exit = True
        self.show_path = True#False
        self.show_start = True
        
        
    def start(self):
        
        logged = 0
        
        for throw in range(0, self.throws):
            
            # Delete last ray from visualiser
            if Visualiser.VISUALISER_ON:
                for obj in self.visualiser.display.objects:
                    if obj.__class__ is visual.cylinder: # can say either box or 'box'
                        if obj.radius < 0.001:
                            obj.visible = False
                
            if self.show_log:
                print "Photon number:", throw
            else:
                print "Photon number:", throw, "\r",
                sys.stdout.flush()
            
            photon = self.source.photon()
            photon.visualiser = self.visualiser
            photon.scene = self.scene
            photon.material = self.source
            photon.show_log = self.show_log
            
            a = list(photon.position)
            if self.show_start:
                self.visualiser.addSmallSphere(a)
            
            step = 0
            while photon.active and step < self.steps:
                
                if photon.exit_device is not None:
                    
                    # The exit
                    if photon.exit_device.shape.on_surface(photon.position):
                        
                        # Is the ray heading towards or out of a surface?
                        normal = photon.exit_device.shape.surface_normal(photon.ray, acute=False)
                        rads = angle(normal, photon.ray.direction)
                        #print photon.exit_device.shape.surface_identifier(photon.position), 'normal', normal, 'ray dir', photon.direction, 'angle' , np.degrees(rads)
                        if rads < np.pi/2:
                            bound = "Out"
                            #print "OUT"
                        else:
                            bound = "In"
                            #print "IN"
                        
                        self.database.log(photon, surface_normal=photon.exit_device.shape.surface_normal(photon), surface_id=photon.exit_device.shape.surface_identifier(photon.position), ray_direction_bound=bound)
                        
                else:
                    self.database.log(photon)
                
                #import pdb; pdb.set_trace()
                wavelength = photon.wavelength
                #photon.visualiser.addPhoton(photon)
                photon = photon.trace()
                
                if step == 0:
                    # The ray has hit the first object. 
                    # Cache this for later use. If the ray is not 
                    # killed then log data.
                    #import pdb; pdb.set_trace()
                    entering_photon = copy(photon)
                
                #print "Step number:", step
                b = list(photon.position)                
                
                if self.show_lines and photon.active == True:
                    self.visualiser.addLine(a,b, colour=wav2RGB(photon.wavelength))
                
                if self.show_path and photon.active == True:
                    self.visualiser.addSmallSphere(b)
                
                #import pdb; pdb.set_trace()
                
                if photon.active == False and photon.container == self.scene.bounds:
                    
                    if self.show_exit:
                        self.visualiser.addSmallSphere(a, colour=[.33,.33,.33])
                        self.visualiser.addLine(a, a + 0.01*photon.direction, colour=wav2RGB(wavelength))
                    
                    # Record photon that has made it to the bounds
                    if step == 0:
                        if self.show_log: print "   * Photon hit scene bounds without previous intersections *"
                    else:
                        if self.show_log: print "   * Reached Bounds *"
                        photon.exit_device.log(photon)
                        #self.database.log(photon)
                        
                    #entering_photon.exit_device.log(entering_photon)
                    #assert logged == throw, "Logged (%s) and thorw (%s) not equal" % (str(logged), str(throw))
                    logged = logged + 1
                    
                elif photon.active == False:                    
                    #print photon.exit_device.name
                    photon.exit_device = photon.container
                    photon.container.log(photon)
                    self.database.log(photon)
                    if entering_photon.container == photon.scene.bounds:
                        if self.show_log: print "   * Photon hit scene bounds without previous intersections *"
                    else:
                        #try:
                        entering_photon.container.log(entering_photon)
                        #self.database.log(photon)
                        #except:
                        #    entering_photon.container.log_in_volume(entering_photon)
                    #assert logged == throw, "Logged (%s) and thorw (%s) not equal" % (str(logged), str(throw))
                    logged = logged + 1
                
                
                a = b
                step = step + 1
                self.totalsteps = self.totalsteps + 1
                if step >= self.steps:
                    # We need to kill the photon because it is bouncing around in a locked path
                    self.killed = self.killed + 1
                    photon.killed = True
                    self.database.log(photon)
                    if self.show_log: 
                        print "   * Reached Max Steps *"