def __init__(self, x=None, y=None, file=None): super(Spectrum, self).__init__() """Initialised with x and y which are array-like data of the same length. x must have units of wavelength (that is in nanometers), y can an arbitrary units. However, if the Spectrum is representing an absorption coefficient y must have units of (1/m).""" if file != None: try: data = np.loadtxt(file) except Exception as e: print "Failed to load data from file, %s", str(file) print e exit(1) self.x = np.array(data[:,0], dtype=np.float32) self.y = np.array(data[:,1], dtype=np.float32) elif (x != None and y != None): self.x = np.array(x, dtype=np.float32) self.y = np.array(y, dtype=np.float32) else: # We need to make some data up -- i.e. flat over the full model range self.x = np.array([200, 500, 750, 4000], dtype=np.float32) self.y = np.array([0, 0, 0, 0], dtype=np.float32) if len(self.x) == 0: # We need to make some data up -- i.e. flat over the full model range self.x = np.array([200, 500, 750, 4000], dtype=np.float32) self.y = np.array([0, 0, 0, 0], dtype=np.float32) elif len(self.x) == 1: # We have a harder time at making up some data xval = self.x[0] yval = self.y[0] bins = np.arange(np.floor( self.x[0] - 1), np.ceil(self.x[0] + 2)) indx = np.where(bins==xval)[0][0] self.x = np.array(bins, dtype=np.float32) self.y = np.zeros(len(self.x), dtype=np.float32) self.y[indx] = np.array(yval, dtype=np.float32) # Make the 'spectrum' self.spectrum = interp1d(self.x, self.y, bounds_error=False, fill_value=0.0) # Make the pdf for wavelength lookups try: # Convert the (x,y) point pairs to a histogram of bins and frequencies bins = np.hstack([self.x, 2*self.x[-1] - self.x[-2]]) except IndexError: print "Index Error from array, ", self.x cdf = np.cumsum(self.y) pdf = cdf/max(cdf) pdf = np.hstack([0,pdf[:]]) self.pdf_lookup = interp1d(bins, pdf, bounds_error=False, fill_value=0.0) self.pdfinv_lookup = interp1d(pdf, bins, bounds_error=False, fill_value=0.0)
def __init__(self, x=None, y=None, file=None): super(Spectrum, self).__init__() """Initialised with x and y which are array-like data of the same length. x must have units of wavelength (that is in nanometers), y can an arbitrary units. However, if the Spectrum is representing an absorption coefficient y must have units of (1/m).""" if file != None: try: data = np.loadtxt(file) except Exception as e: print "Failed to load data from file, %s", str(file) print e exit(1) self.x = data[:,0] self.y = data[:,1] elif (x != None and y != None): self.x = np.array(x) self.y = np.array(y) else: # We need to make some data up -- i.e. flat over the full model range self.x = np.array([200, 500, 750, 4000]) self.y = np.array([0, 0, 0, 0]) if len(self.x) == 0: # We need to make some data up -- i.e. flat over the full model range self.x = np.array([200, 500, 750, 4000]) self.y = np.array([0, 0, 0, 0]) elif len(self.x) == 1: # We have a harder time at making up some data xval = self.x[0] yval = self.y[0] bins = np.arange(np.floor( self.x[0] - 1), np.ceil(self.x[0] + 2)) indx = np.where(bins==xval)[0][0] self.x = np.array(bins) self.y = np.zeros(len(self.x)) self.y[indx] = yval # Make the 'spectrum' self.spectrum = interp1d(self.x, self.y, bounds_error=False, fill_value=0.0) # Make the pdf for wavelength lookups try: # Convert the (x,y) point pairs to a histogram of bins and frequencies bins = np.hstack([self.x, 2*self.x[-1] - self.x[-2]]) except IndexError: print "Index Error from array, ", self.x cdf = np.cumsum(self.y) pdf = cdf/max(cdf) pdf = np.hstack([0,pdf[:]]) self.pdf_lookup = interp1d(bins, pdf, bounds_error=False, fill_value=0.0) self.pdfinv_lookup = interp1d(pdf, bins, bounds_error=False, fill_value=0.0)
def trace(self, photon, free_pathlength): '''Will apply absorption and emission probabilities to the photon along its free path in the present geometrical container and return the result photon for tracing. See help(material.trace) for how this is done for a single material because the same principle applies. The ensemble absorption coefficient is found for the specified photon to determine if absorption occurs. The absorbed material its self is found at random from a distrubution weighted by each of the component absorption coefficients. The resultant photon is returned with possibily with a new position, direction and wavelength. If the photon is absorbed and not emitted the photon is retuned but its active property is set to False. ''' # Clear state using for collecting statistics photon.absorber_material = None photon.emitter_material = None absorptions = self.all_absorption_coefficients(photon.wavelength) absorption_coefficient = absorptions.sum() sampled_pathlength = -np.log( 1 - np.random.uniform()) / absorption_coefficient #Absorption occurs. if (sampled_pathlength < free_pathlength): # Move photon along path to the absorption point photon.absorption_counter = photon.absorption_counter + 1 photon.position = photon.position + sampled_pathlength * photon.direction # Find the absorption material count = len(self.materials) bins = range(0, count + 1) cdf = np.cumsum(absorptions) pdf = cdf / max(cdf) pdf = np.hstack([0, pdf[:]]) pdfinv_lookup = interp1d(pdf, bins, bounds_error=False, fill_value=0.0) absorber_index = int(np.floor(pdfinv_lookup(np.random.uniform()))) material = self.materials[absorber_index] photon.material = material photon.absorber_material = material self.emission = material.emission self.absorption = material.absorption self.quantum_efficiency = material.quantum_efficiency #Emission occurs. if (np.random.uniform() < material.quantum_efficiency): print " * Re-emitted *" photon.reabs = photon.reabs + 1 photon.emitter_material = material photon = material.emission( photon ) # Generates a new photon with red-shifted wavelength, new direction and polariation (if included in simulation) return photon else: print " * Photon Lost *" #Emission does not occur. Now set active = False ans return photon.active = False return photon else: #Absorption does not occur. The photon reaches the edge, update it's position and return photon.position = photon.position + free_pathlength * photon.direction return photon
def trace(self, photon, free_pathlength): '''Will apply absorption and emission probabilities to the photon along its free path in the present geometrical container and return the result photon for tracing. See help(material.trace) for how this is done for a single material because the same principle applies. The ensemble absorption coefficient is found for the specified photon to determine if absorption occurs. The absorbed material its self is found at random from a distrubution weighted by each of the component absorption coefficients. The resultant photon is returned with possibily with a new position, direction and wavelength. If the photon is absorbed and not emitted the photon is retuned but its active property is set to False. ''' # Clear state using for collecting statistics photon.absorber_material = None photon.emitter_material = None absorptions = self.all_absorption_coefficients(photon.wavelength) absorption_coefficient = absorptions.sum() sampled_pathlength = -np.log(1 - np.random.uniform())/absorption_coefficient #Absorption occurs. if (sampled_pathlength < free_pathlength): # Move photon along path to the absorption point photon.absorption_counter = photon.absorption_counter + 1 photon.position = photon.position + sampled_pathlength * photon.direction # Find the absorption material count = len(self.materials) bins = range(0, count+1) cdf = np.cumsum(absorptions) pdf = cdf/max(cdf) pdf = np.hstack([0,pdf[:]]) pdfinv_lookup = interp1d(pdf, bins, bounds_error=False, fill_value=0.0) absorber_index = int(np.floor(pdfinv_lookup(np.random.uniform()))) material = self.materials[absorber_index] photon.material = material photon.absorber_material = material self.emission = material.emission self.absorption = material.absorption self.quantum_efficiency = material.quantum_efficiency #Emission occurs. if (np.random.uniform() < material.quantum_efficiency): print " * Re-emitted *" photon.reabs = photon.reabs + 1 photon.emitter_material = material photon = material.emission(photon) # Generates a new photon with red-shifted wavelength, new direction and polariation (if included in simulation) return photon else: print " * Photon Lost *" #Emission does not occur. Now set active = False ans return photon.active = False return photon else: #Absorption does not occur. The photon reaches the edge, update it's position and return photon.position = photon.position + free_pathlength * photon.direction return photon