def render_task(self, task_index: int, bucket_index: int, bucket_order_info: BucketOrderInfo, sample, renderer: Renderer): sampler = self.main_sampler.get_sub_sampler(bucket_index, bucket_order_info) if sampler is None: return print("start render task : id(" + str(task_index) + ") (" + str(sampler.bucket_extend.start_x) + "," + str( sampler.bucket_extend.start_y) + ") " + "(" + str(sampler.bucket_extend.end_x - 1) + "," + str( sampler.bucket_extend.end_y - 1) + ")") self.draw_bucket_extend(sampler.bucket_extend) pixels = [] maxSamples = sampler.get_maximum_sample_count() samples = [] rays = [] Ls = [] Ts = [] intersections = [] for n in range(maxSamples): samples.append(deepcopy(sample)) rays.append(Ray()) Ls.append(Spectrum(0.0)) Ts.append(Spectrum(0.0)) intersections.append(Intersection()) # preallocate array for each pixels # rays = [Ray()]*maxSamples # Ls = [Spectrum(0.0)]*maxSamples # Ts = [Spectrum(0.0)]*maxSamples # intersections = [Intersection()]*maxSamples while True: if sampler.get_more_samples(samples) == 0: break for i in range(len(samples)): rays[i] = self.camera.generate_ray(samples[i]) Ls[i] = renderer.get_li(self.scene, rays[i], intersections[i], samples[i]) s = Spectrum(0.0) for i in range(len(samples)): s += Ls[i] s /= float(len(samples)) s = s.get_clamp(0.0, 1.0) pixels.append(s) print("end render task " + str(task_index)) return pixels, sampler.bucket_extend
def Le(self, w): """Return the light emitted by the object.""" if self.primitive is None: logger.error("Intersect.Le() called with no primitive.") return Spectrum(0.0) area = self.primitive.get_area_light() if area: return area.L(self.dg.p, self.dg.nn, w) else: return Spectrum(0.0)
def EstimateDirect(scene: Scene, renderer: Renderer, light: Light, p: Point3d, n: Normal, wo: Vector3d, time: float, bsdf: BSDF, lightSample: LightSample, bsdfSample: BSDFSample, BxDFTypeFlag: int) -> Spectrum: Ld = Spectrum(0.0) visibility = VisibilityTester() wi, Li, lightPdf = light.Sample_L1(p, lightSample, time, visibility) if lightPdf > 0.0 and not Li.get_is_black(): f = bsdf.f(wo, wi, BxDFTypeFlag) if not f.get_is_black() and visibility.Unoccluded(scene): # Add light's contribution to reflected radiance #Li *= visibility.Transmittance(scene, renderer, None) inv_lightPdf = 1.0 / lightPdf if light.get_is_delta_light(): Ld += f * Li * math.fabs(Vector3d.dot(wi, n)) * inv_lightPdf else: bsdfPdf = bsdf.get_Pdf(wo, wi, BxDFTypeFlag) weight = PowerHeuristic(1, lightPdf, 1, bsdfPdf) Ld += f * Li * math.fabs(Vector3d.dot(wi, n)) * weight * inv_lightPdf # Sample BSDF with multiple importance sampling if not light.get_is_delta_light(): wi, bsdfPdf, sampledType, f = bsdf.Sample_f(wo, bsdfSample, BxDFTypeFlag) if not f.get_is_black() and bsdfPdf > 0.0: weight = 1.0 if not (BxDFTypeFlag & BxDFType.BSDF_SPECULAR): lightPdf = light.get_pdf(p, wi) if lightPdf == 0.0: return Ld weight = PowerHeuristic(1, bsdfPdf, 1, lightPdf) # Add light contribution from BSDF sampling lightIsect = Intersection() Li = Spectrum(0.0) ray = Ray(p, wi, 1e-3, infinity_max_f, time) if scene.get_intersection(ray, lightIsect): if lightIsect.primitive.GetAreaLight() == light: Li = lightIsect.Le(-wi) else: Li = light.Le(ray) if not Li.get_is_black(): Li *= 1.0 #todo renderer.Transmittance(scene, ray, None) Ld += f * Li * math.fabs(Vector3d.dot(wi, n)) * weight / bsdfPdf return Ld
def Li(self, scene, ray, sample, rng, intersection=None, T=None): """Compute the incident radiance along a given ray.""" # allocate local variables for isect and T if needed if not T: T = Spectrum(0.0) if not intersection: intersection = Intersection() Li = Spectrum(0.0) hit = scene.intersect(ray, intersection) if hit: Li = self.surface_integrator.Li(scene, self, ray, intersection, sample, rng) else: # handle ray that doesn't intersect any geometry for light in scene.lights: Li += light.Le(ray) # Lvi = self.volume_integrator.Li(scene, self, ray, sample, rng, T) # return T * Li + Lvi, intersection return Li, intersection, T
def Li(self, scene, renderer, ray, intersection, sample, rng): """Computes the radiance along a ray.""" return Spectrum(1.0) L = Spectrum(0.0) # evaluate BSDF at hit point bsdf = intersection.get_bsdf(ray) # initialize common variables for Whitted integrator p = bsdf.dg_shading.p n = bsdf.dg_shading.nn wo = -ray.d # compute emitted light if ray hit an area light source L += intersection.Le(wo) # add contribution of each light source for light in self.scene.lights: light_sample = LightSample.from_rng(rng) Li, wi, pdf, visibility = light.sample_L(p, intersection.ray_epsilon, light_sample, ray.time) if Li.is_black() or pdf == 0.0: continue f = bsdf.f(wo, wi) if (not f.is_black()) and visibility.unoccluded(scene): L += f * Li * abs_dot(wi, n) * visibility.transmittance( scene, renderer, sample, rng) / pdf if ray.depth + 1 < self.max_depth: # trace rays for specular reflection and refraction L += specular_reflect(ray, bsdf, rng, intersection, renderer, scene, sample) L += specular_transmit(ray, bsdf, rng, intersection, renderer, scene, sample) return L
def initialize(self, lattice): # read settings settings = Settings()['generator']['photons'] self._enabled = settings['enabled'] self._full_events = settings['full_events'] self._nth_step = settings['nth_step'] self._time = settings['time'] self._energy_cutoff = settings['energy_cutoff'] self._sigma_h = settings['sigma']['horizontal'] self._sigma_v = settings['sigma']['vertical'] self._stepsize_h = 2.0 * self._sigma_h / settings['steps']['horizontal'] self._stepsize_v = 2.0 * self._sigma_v / settings['steps']['vertical'] self._crossing_angle = Settings()['machine']['crossing_angle'] self._region_enabled = settings['region']['enabled'] if settings['region']['range'][0] < settings['region']['range'][1]: self._region_left = settings['region']['range'][0] self._region_right = settings['region']['range'][1] else: self._region_left = settings['region']['range'][1] self._region_right = settings['region']['range'][0] self._target_zone_enabled = settings['target_zone']['enabled'] self._target_zone_radius = settings['target_zone']['radius'] self._target_zone_boundary = settings['target_zone']['boundary'] # create synchrotron radiation power spectrum PDF self._spectrum = Spectrum() self._spectrum.initialize(settings['spectrum']['resolution'], settings['spectrum']['cutoff'], settings['spectrum']['seed'], settings['spectrum']['interpolation']) # internal parameters self._lattice = lattice self._call_count = 0 self._dl = 0.0 # internal constants and pre-calculated factors self._alpha = 1.0 / 137.035999074 self._speed_of_light = 2.99792458e8 # [m/s] self._hbar = 6.58211928e-25 # [GeV s] self._gamma = Settings()['machine']['beam_energy'] / 510.998928e-6 self._current = Settings()['machine']['beam_current'] * 6.241508e18 self._num_photon_factor = (5.0 / (2.0*math.sqrt(3))) * \ self._gamma * self._alpha * \ self._current * self._time self._crit_e_factor = 3.0 / 2.0 * self._speed_of_light * \ self._hbar * (self._gamma**3)
def __init__(self, cap=None): self.captures = [] self.dataTypes = [] self.x = [] self.y = [] self.xkey = '' self.ykey = '' self.freqMode = 'Frequency' self.mode = 'Combined' self.scansIncluded = [] self.histMode = True self.binsize = 0.03 self.spectra = [] self.combSpectrum = Spectrum() if not cap == None: self.addCapture(cap)
def run(self): """Execute the task.""" print "executing task %d/%d" % (self.task_num, self.task_count) # get sub-sampler for SamplerRendererTask sampler = self.main_sampler.get_sub_sampler(self.task_num, self.task_count) if not sampler: return # Declare local variables used for rendering loop rng = RNG(self.task_num) # allocate space for samples and intersections max_samples = sampler.maximum_sample_count() samples = self.orig_sample.duplicate(max_samples) rays = [None] * max_samples Ls = [None] * max_samples Ts = [None] * max_samples isects = [] # Intersection[max_samples] for i in range(max_samples): isects.append(Intersection()) # get samples from Sampler and update image while True: sample_count = sampler.get_more_samples(samples, rng) # if no more samples to compute, exit if sample_count <= 0: break # generate camera rays and compute radiance along rays for i in range(sample_count): # find camera ray for samples[i] ray_weight, ray_diff = self.camera.generate_ray_differential( samples[i]) rays[i] = ray_diff coeff = 1.0 / math.sqrt(sampler.samples_per_pixel) ray_diff.scale_differentials(coeff) # evaluate radiance along camera ray if ray_weight > 0.0: radiance, intersection, Ts_i = \ self.renderer.Li(self.scene, ray_diff, samples[i], rng, isects[i]) Ls_i = ray_weight * radiance else: Ls_i = Spectrum(0.0) Ts_i = Spectrum(1.0) Ls[i] = Ls_i Ts[i] = Ts_i # check for unexpected radiance values if Ls_i.has_nan(): logger.error( "Not-a-number radiance value returned for image sample. Setting to black." ) Ls_i = Spectrum(0.0) elif Ls_i.y() < -1e-5: logger.error( "Negative luminance value, %f, returned for image sample. Setting to black." % Ls_i.y()) Ls_i = Spectrum(0.0) elif Ls_i.y() == float('inf'): logger.error( "Infinite luminance value returned for image sample. Setting to black." ) Ls_i = Spectrum(0.0) # report sample results to Sampler, add contributions to image if sampler.report_results(samples, rays, Ls, isects, sample_count): for i in range(sample_count): self.camera.film.add_sample(samples[i], Ls[i]) # clean up after SamplerRendererTask is done with its image region pass
def Li(self, scene, renderer: Renderer, r: Ray, intersection: Intersection, sample: Sample) -> Spectrum: # Declare common path integration variables pathThroughput = Spectrum(1.0) L = Spectrum(0.0) ray = deepcopy(r) specularBounce = False localIsect = Intersection() isectp = intersection bounces = 0 while True: # Possibly add emitted light at path vertex if bounces == 0 or specularBounce: L += pathThroughput * isectp.Le(-ray.direction) # Sample illumination from lights to find path contribution bsdf = isectp.get_bsdf(ray) p = bsdf.dgShading.point n = bsdf.dgShading.normal wo = -ray.direction if bounces < self.maxDepth: L += pathThroughput * UniformSampleOneLight(scene, renderer, p, n, wo, ray.time, bsdf, sample, self.lightSampleOffsets[bounces], self.bsdfSampleOffsets[bounces], self.lightNumOffset[bounces]) else: L += pathThroughput * UniformSampleOneLight(scene, renderer, p, n, wo, ray.time, bsdf, sample) # Sample BSDF to get new path direction # Get _outgoingBSDFSample_ for sampling new path direction if bounces < self.maxDepth: outgoingBSDFSample = BSDFSample.create_from_sample(sample, self.pathSampleOffsets[bounces], 0) else: outgoingBSDFSample = BSDFSample.create_from_random() wi, pdf, flags, f = bsdf.Sample_f(wo, outgoingBSDFSample, BxDFType.BSDF_ALL) if f.get_is_black() or pdf == 0.0: break specularBounce = (flags & BxDFType.BSDF_SPECULAR) != 0 pathThroughput *= f * math.fabs(Vector3d.dot(wi, n)) / pdf ray = Ray(p, wi, 0.01, ray.max_t) # Possibly terminate the path if bounces > 3: continueProbability = min(0.5, pathThroughput.y()) if random() > continueProbability: break pathThroughput /= continueProbability if bounces == self.maxDepth: break # Find next vertex of path if not scene.get_intersection(ray, localIsect): if specularBounce: for i in range(scene.lights.size()): L += pathThroughput * scene.lights[i].get_Le(ray) break # pathThroughput *= renderer->Transmittance(scene, ray, NULL, rng, arena); isectp = localIsect bounces += 1 return L
def enterParamSet(self, ctx): print("enter paramset") p = ctx.paramSetLeft() a = str(p.STRING()).replace('"', '').split(' ') param_type = a[0] param_name = a[1] print("-->" + param_name) if param_type == 'point': print("-->point") i = 0 values = [] while True: if ctx.NUMBER(i) is None: break values.append( Point3d(float(str(ctx.NUMBER(i))), float(str(ctx.NUMBER(i + 1))), float(str(ctx.NUMBER(i + 2))))) i += 3 self.currentParamSet.add_point(param_name, values) elif param_type == 'float': print("-->float") i = 0 values = [] while True: if ctx.NUMBER(i) is None: break values.append(float(str(ctx.NUMBER(i)))) i += 1 self.currentParamSet.add_float(param_name, values) elif param_type == 'integer': print("-->int") i = 0 values = [] while True: if ctx.NUMBER(i) is None: break values.append(int(str(ctx.NUMBER(i)))) i += 1 self.currentParamSet.add_int(param_name, values) elif param_type == 'string': print("-->string") i = 0 values = [] while True: if ctx.STRING(i) is None: break values.append(str(ctx.STRING(i)).replace("\"", "")) i += 1 if len(values) == 1: self.currentParamSet.add_string(param_name, values[0]) else: self.currentParamSet.add_string(param_name, values) elif param_type == 'color': print("-->color") i = 0 values = [] while True: if ctx.NUMBER(i) is None: break values.append(float(str(ctx.NUMBER(i)))) i += 1 self.currentParamSet.add_spectrum(param_name, Spectrum.create_from_array(values))
def run(self): """Execute the task.""" print "executing task %d/%d" % (self.task_num, self.task_count) # get sub-sampler for SamplerRendererTask sampler = self.main_sampler.get_sub_sampler(self.task_num, self.task_count) if not sampler: return # Declare local variables used for rendering loop rng = RNG(self.task_num) # allocate space for samples and intersections max_samples = sampler.maximum_sample_count() samples = self.orig_sample.duplicate(max_samples) rays = [None] * max_samples Ls = [None] * max_samples Ts = [None] * max_samples isects = [] # Intersection[max_samples] for i in range(max_samples): isects.append(Intersection()) # get samples from Sampler and update image while True: sample_count = sampler.get_more_samples(samples, rng) # if no more samples to compute, exit if sample_count <= 0: break # generate camera rays and compute radiance along rays for i in range(sample_count): # find camera ray for samples[i] ray_weight, ray_diff = self.camera.generate_ray_differential(samples[i]) rays[i] = ray_diff coeff = 1.0 / math.sqrt(sampler.samples_per_pixel) ray_diff.scale_differentials(coeff) # evaluate radiance along camera ray if ray_weight > 0.0: radiance, intersection, Ts_i = \ self.renderer.Li(self.scene, ray_diff, samples[i], rng, isects[i]) Ls_i = ray_weight * radiance else: Ls_i = Spectrum(0.0) Ts_i = Spectrum(1.0) Ls[i] = Ls_i Ts[i] = Ts_i # check for unexpected radiance values if Ls_i.has_nan(): logger.error( "Not-a-number radiance value returned for image sample. Setting to black.") Ls_i = Spectrum(0.0) elif Ls_i.y() < -1e-5: logger.error( "Negative luminance value, %f, returned for image sample. Setting to black." % Ls_i.y()) Ls_i = Spectrum(0.0) elif Ls_i.y() == float('inf'): logger.error( "Infinite luminance value returned for image sample. Setting to black.") Ls_i = Spectrum(0.0) # report sample results to Sampler, add contributions to image if sampler.report_results(samples, rays, Ls, isects, sample_count): for i in range(sample_count): self.camera.film.add_sample(samples[i], Ls[i]) # clean up after SamplerRendererTask is done with its image region pass
class Photons(): """ Integrate over the beam and create the photons """ def __init__(self): pass def initialize(self, lattice): # read settings settings = Settings()['generator']['photons'] self._enabled = settings['enabled'] self._full_events = settings['full_events'] self._nth_step = settings['nth_step'] self._time = settings['time'] self._energy_cutoff = settings['energy_cutoff'] self._sigma_h = settings['sigma']['horizontal'] self._sigma_v = settings['sigma']['vertical'] self._stepsize_h = 2.0 * self._sigma_h / settings['steps']['horizontal'] self._stepsize_v = 2.0 * self._sigma_v / settings['steps']['vertical'] self._crossing_angle = Settings()['machine']['crossing_angle'] self._region_enabled = settings['region']['enabled'] if settings['region']['range'][0] < settings['region']['range'][1]: self._region_left = settings['region']['range'][0] self._region_right = settings['region']['range'][1] else: self._region_left = settings['region']['range'][1] self._region_right = settings['region']['range'][0] self._target_zone_enabled = settings['target_zone']['enabled'] self._target_zone_radius = settings['target_zone']['radius'] self._target_zone_boundary = settings['target_zone']['boundary'] # create synchrotron radiation power spectrum PDF self._spectrum = Spectrum() self._spectrum.initialize(settings['spectrum']['resolution'], settings['spectrum']['cutoff'], settings['spectrum']['seed'], settings['spectrum']['interpolation']) # internal parameters self._lattice = lattice self._call_count = 0 self._dl = 0.0 # internal constants and pre-calculated factors self._alpha = 1.0 / 137.035999074 self._speed_of_light = 2.99792458e8 # [m/s] self._hbar = 6.58211928e-25 # [GeV s] self._gamma = Settings()['machine']['beam_energy'] / 510.998928e-6 self._current = Settings()['machine']['beam_current'] * 6.241508e18 self._num_photon_factor = (5.0 / (2.0*math.sqrt(3))) * \ self._gamma * self._alpha * \ self._current * self._time self._crit_e_factor = 3.0 / 2.0 * self._speed_of_light * \ self._hbar * (self._gamma**3) def create(self, step, beam, output, hepevt): if not self._enabled: return # accumulate steps only inside magnets and, if enabled, # inside the region if (not step.in_vacuum) and \ (not self._region_enabled or \ (self._region_enabled and \ step.s0ip >= self._region_left and step.s0ip <= self._region_right)): self._dl += step.dl self._call_count += 1 # radiate photons if the n-th step is reached, # the current step is on a magnet to vacuum boundary, # or the region is enabled and the step leaves the region if (self._call_count >= self._nth_step) or \ (self._call_count > 0 and step.on_boundary) or \ (self._region_enabled and self._call_count > 0 and step.ds < 0.0 and \ step.s0ip <= self._region_left) or \ (self._region_enabled and self._call_count > 0 and step.ds > 0.0 and \ step.s0ip >= self._region_right): self._integrate_beam(math.fabs(self._dl), step, beam, output, hepevt) self._dl = 0.0 self._call_count = 0 def write_spectrum(self, output): self._spectrum.write(output) def _intersect_target_zone(self, vertex, direction): """ Target zone is an z-axis aligned cylinder with an inner and an outer radius and a lower and upper boundary. This code intersects a line with the cylinder, not a ray! That's ok for the SyncRad Generator, as this shouldn't introduce too many false intersections as long as the generation is done in a way such that the photons travel towards the IP. """ # calculate slopes if math.fabs(direction[2]) > 0.0000000001: slope_xz = direction[0] / direction[2] slope_yz = direction[1] / direction[2] else: slope_xz = 0.0 slope_yz = 0.0 # calculate the distance from the z-axis (radius) that the ray has at the # lower and upper z-boundary of the cylinder. def calc_radius2(boundary): x_b = slope_xz*(boundary-vertex[2]) + vertex[0] y_b = slope_yz*(boundary-vertex[2]) + vertex[1] return x_b**2 + y_b**2 r_low = calc_radius2(self._target_zone_boundary[0]) r_up = calc_radius2(self._target_zone_boundary[1]) # since it is a z-axis aligned cylinder, the radius can simply be compared # to the cylinder radii, in order to check for the intersection of the ray. radius2 = [self._target_zone_radius[0]**2, self._target_zone_radius[1]**2] return ((r_low < radius2[1]) and (r_up > radius2[0])) or \ ((r_up < radius2[1]) and (r_low > radius2[0])) def _integrate_beam(self, dl, step, beam, output, hepevt): """ integrate over the beam profile """ total_number_photons = 0 total_number_photons_cut = 0 k1s = [] for region in self._lattice.get(step.s0ip): idx = region.index(step.s0ip) k1s.append([region.k1(idx), region.sk1(idx)]) hsize, vsize, ch, cv = beam.size() prob_norm_1 = 1.0 / (2.506628 * hsize * vsize) prob_norm_2 = 1.0 / (2.0*math.pi * hsize * vsize) weight_factor = self._stepsize_h * self._stepsize_v * hsize * vsize xstep = self._stepsize_h * hsize ystep = self._stepsize_v * vsize xs_max = self._sigma_h * hsize ys_max = self._sigma_v * vsize cx_s = math.sin(self._crossing_angle) cx_c = math.cos(self._crossing_angle) xs = -1.0 * self._sigma_h * hsize + 0.5*xstep while xs <= xs_max: ys = -1.0 * self._sigma_v * vsize + 0.5*ystep while ys <= ys_max: # calculate local radius local_gh = step.gh local_gv = step.gv for k1 in k1s: local_gh += (k1[0] * xs) - (k1[1] * ys) local_gv += (k1[0] * ys) + (k1[1] * xs) rho_inv = math.sqrt(local_gh**2 + local_gv**2) # calculate weight prob = 0.0 nsigh = xs / hsize nsigv = ys / vsize # beam profile. Either Talman tails or Gaussian if (math.fabs(nsigv) > 5.0) and (beam.emitv / beam.emith < 0.2): prob = prob_norm_1 * math.exp(-0.5*nsigh**2) * \ math.exp(-7.4 -1.2*math.fabs(nsigv)) else: prob = prob_norm_2 * math.exp(-0.5*(nsigh**2 + nsigv**2)) weight = prob * weight_factor # calculate number of radiated photons num_photons = int(self._num_photon_factor * rho_inv * weight * dl) total_number_photons += num_photons if num_photons > 0: # calculate critical energy crit_e = self._crit_e_factor * rho_inv # calculate vertex vx = (cx_c*(step.xip+xs)) + (cx_s*step.zip) vy = step.yip+ys vz = (cx_c*step.zip) - (cx_s*(step.xip+xs)) # calculate momentum px_temp = -step.zip * ((math.pi - step.xip_prime) + (ch * xs)) py_temp = -step.zip * (step.yip_prime + (cv * ys)) pz_temp = -step.zip # rotate momentum into Geant4 space px = (cx_c*px_temp) + (cx_s*pz_temp) py = py_temp pz = (cx_c*pz_temp) - (cx_s*px_temp) norm = 1.0/math.sqrt(px**2 + py**2 + pz**2) # if the target zone feature is on, only write events if # the photons will hit the zone. if (not self._target_zone_enabled) or \ (self._target_zone_enabled and \ self._intersect_target_zone([vx, vy, vz], [px, py, pz])): # if full event writing is turned on, get the energies # for all radiated photons and write them into the # event file if self._full_events: energies = self._spectrum.random(crit_e, num_photons, self._energy_cutoff) if len(energies) > 0: evt = hepevt.event(vx, vy, vz) for e in energies: evt.add(px*e*norm, py*e*norm, pz*e*norm) evt.commit() total_number_photons_cut += len(energies) else: evt = hepevt.event(vx, vy, vz, num_photons=num_photons, critical_e=crit_e) evt.add(px*norm, py*norm, pz*norm) evt.commit() ys += ystep xs += xstep output.write(["%f:%i:%i:%e:%e:%e:%e\n"%(step.s0ip, total_number_photons, total_number_photons_cut, step.x, step.y, step.xp, step.yp)])