from cherab.jet.cameras.kl1 import load_kl1_camera world = World() import_jet_mesh(world) # run1706184 jsimpson/edge2d/jet/85274/aug0717/seq#23 /home/jsimpson/cmg/catalog/edge2d/jet/85274/aug0717/seq#23 # run1706188 jsimpson/edge2d/jet/85274/aug0717/seq#27 edge2d_sim = load_edge2d_from_eproc('/home/jsimpson/cmg/catalog/edge2d/jet/85274/aug0717/seq#23/tran') plasma = edge2d_sim.create_plasma(parent=world) plasma.atomic_data = OpenADAS(permit_extrapolation=True) # Pick emission models d_alpha = Line(deuterium, 0, (3, 2)) plasma.models = [ExcitationLine(d_alpha), RecombinationLine(d_alpha)] # plt.ion() # Setup camera for interactive use... power_unfiltered = PowerPipeline2D(display_unsaturated_fraction=0.96, name="Unfiltered Power (W)", display_progress=False) power_unfiltered.display_update_time = 15 camera = load_kl1_camera(parent=world, pipelines=[power_unfiltered]) camera.pixel_samples = 150 camera.ray_max_depth = 3 camera.observe() np.save('KL1_run1706184_reflecting_150', power_unfiltered.frame.mean) power_unfiltered.save('KL1_run1706184_reflecting_150.png')
plasma.composition = [d0_species, d1_species, n1_species] # setup the Balmer lines hydrogen_I_410 = Line(deuterium, 0, (6, 2)) # n = 6->2: 410.12nm hydrogen_I_396 = Line(deuterium, 0, (7, 2)) # n = 7->2: 396.95nm # setup the Nitrgon II line with multiplet splitting instructions nitrogen_II_404 = Line(nitrogen, 1, ("2s2 2p1 4f1 3G13.0", "2s2 2p1 3d1 3F10.0")) multiplet = [[403.509, 404.132, 404.354, 404.479, 405.692], [0.205, 0.562, 0.175, 0.029, 0.029]] # add all lines to the plasma plasma.models = [ ExcitationLine(hydrogen_I_410, lineshape=StarkBroadenedLine), RecombinationLine(hydrogen_I_410, lineshape=StarkBroadenedLine), ExcitationLine(hydrogen_I_396, lineshape=StarkBroadenedLine), RecombinationLine(hydrogen_I_396, lineshape=StarkBroadenedLine), ExcitationLine(nitrogen_II_404, lineshape=MultipletLineShape, lineshape_args=[multiplet]), ] # Ray-trace and plot the results plt.ion() r = Ray(origin=Point3D(0, 0, -5), direction=Vector3D(0, 0, 1), min_wavelength=395, max_wavelength=415, bins=2000) s = r.trace(world)
# Setup elements.deuterium lines d_alpha = Line(elements.deuterium, 0, (3, 2)) d_beta = Line(elements.deuterium, 0, (4, 2)) d_gamma = Line(elements.deuterium, 0, (5, 2)) d_delta = Line(elements.deuterium, 0, (6, 2)) d_epsilon = Line(elements.deuterium, 0, (7, 2)) plasma.models = [ Bremsstrahlung(), ExcitationLine(d_alpha), ExcitationLine(d_beta), ExcitationLine(d_gamma), ExcitationLine(d_delta), ExcitationLine(d_epsilon), RecombinationLine(d_alpha), RecombinationLine(d_beta), RecombinationLine(d_gamma), RecombinationLine(d_delta), RecombinationLine(d_epsilon) ] plt.ion() r = Ray(origin=Point3D(0, 0, -5), direction=Vector3D(0, 0, 1), min_wavelength=100, max_wavelength=1000, bins=1e6) s = r.trace(world) plt.plot(s.wavelengths, s.samples)
sim = load_solps_from_mdsplus(mds_server, ref_number) plasma = sim.create_plasma(parent=world) plasma.atomic_data = OpenADAS(permit_extrapolation=True) mesh = sim.mesh vessel = mesh.vessel # Setup deuterium lines d_alpha = Line(deuterium, 0, (3, 2)) d_beta = Line(deuterium, 0, (4, 2)) d_gamma = Line(deuterium, 0, (5, 2)) d_delta = Line(deuterium, 0, (6, 2)) d_epsilon = Line(deuterium, 0, (7, 2)) d_alpha_excit = ExcitationLine(d_alpha, lineshape=StarkBroadenedLine) d_alpha_recom = RecombinationLine(d_alpha, lineshape=StarkBroadenedLine) d_beta_excit = ExcitationLine(d_beta, lineshape=StarkBroadenedLine) d_beta_recom = RecombinationLine(d_beta, lineshape=StarkBroadenedLine) d_gamma_excit = ExcitationLine(d_gamma, lineshape=StarkBroadenedLine) d_gamma_recom = RecombinationLine(d_gamma, lineshape=StarkBroadenedLine) d_delta_excit = ExcitationLine(d_delta, lineshape=StarkBroadenedLine) d_delta_recom = RecombinationLine(d_delta, lineshape=StarkBroadenedLine) d_epsilon_excit = ExcitationLine(d_epsilon, lineshape=StarkBroadenedLine) d_epsilon_recom = RecombinationLine(d_epsilon, lineshape=StarkBroadenedLine) plasma.models = [d_alpha_excit, d_alpha_recom, d_beta_excit, d_beta_recom, d_gamma_excit, d_gamma_recom, d_delta_excit, d_delta_recom, d_epsilon_excit, d_epsilon_recom] start_point = Point3D(1.669, 0, -1.6502) forward_vector = Vector3D(1-1.669, 0, -2+1.6502).normalise() up_vector = Vector3D(0, 0, 1.0)
args = parser.parse_args() sensitivity = load_kl11_sensitivity_matrix(camera='c') voxel_grid = load_kl11_voxel_grid() camera = load_kl11_camera(stride=3) edge2d_sim = load_edge2d_from_eproc(args.sim_path) # edge2d_sim = load_edge2d_from_eproc('/common/cmg/jsimpson/edge2d/runs/run1708151A/tran') plasma = edge2d_sim.create_plasma() plasma.atomic_data = OpenADAS() excitation_model = ExcitationLine(available_lines[args.line]) # excitation_model = ExcitationLine(available_lines['d-alpha']) recombination_model = RecombinationLine(available_lines[args.line]) # recombination_model = RecombinationLine(available_lines['d-alpha']) plasma.models = [excitation_model, recombination_model] class EmissionFunction(PythonFunction3D): def __init__(self, model): self.model = model def __call__(self, x, y, z): direction = Vector3D(1, 0, 0) spectrum = Spectrum(400, 750, 1) observed = self.model.emission(Point3D(x, y, z), direction, spectrum)
def __init__(self, solps_ref_no, view, line, camera, optics='MAST_CI_mod', cherab_down_sample=50, verbose=True, display=False, overwrite=False): """ :param solps_ref_no: int :param view: str :param line: str :param camera: str :param optics: str :param cherab_down_sample: int downsample the image by ths factor in both dimensions, for speed / testing. :param verbose: bool :param display: bool :param overwrite: bool """ self.world = World() self.solps_ref_no = solps_ref_no self.line = line self.view = view self.camera = camera self.optics = optics self.cherab_down_sample = cherab_down_sample self.verbose = verbose self.display = display self.overwrite = overwrite self.radiance = NotImplemented self.spectral_radiance = NotImplemented self.pupil_point = settings.view[self.view]['pupil_point'] self.view_vector = settings.view[self.view]['view_vector'] self.sensor_format = settings.camera[self.camera]['sensor_format'] for s in self.sensor_format: assert s % cherab_down_sample == 0 self.sensor_format_ds = tuple((np.array(self.sensor_format) / cherab_down_sample).astype(np.int)) self.pixel_size = settings.camera[self.camera]['pixel_size'] self.pixel_size_ds = self.pixel_size * cherab_down_sample self.x, self.y, = self.calc_pixel_position(self.pixel_size, self.sensor_format) self.x_pixel = self.x.x_pixel self.y_pixel = self.y.y_pixel self.x_ds = self.x.isel(x=slice(0, self.sensor_format[0], cherab_down_sample, )) self.y_ds = self.y.isel(y=slice(0, self.sensor_format[1], cherab_down_sample, )) self.x_pixel_ds = self.x_ds.x_pixel self.y_pixel_ds = self.y_ds.y_pixel self.chunks = {'x': 800, 'y': 800} # calculate field of view (FOV) (horizontal) using sensor geometry and lens focal lengths f_1, f_2, f_3 = settings.optics[self.optics] sensor_dim = self.sensor_format[0] * self.pixel_size self.fov = 2 * np.arctan((sensor_dim / 2) * f_2 / (f_3 * f_1)) * 180 / np.pi # deg # # file and directory paths self.dir_name = str(solps_ref_no) + '_' + view + '_' + line + '_' + camera self.dir_path = os.path.join(path_saved_data, self.dir_name) fname = 'spec_power.nc' fname_ds = 'spec_power_ds.nc' self.fpath_ds = os.path.join(self.dir_path, fname_ds, ) self.fpath = os.path.join(self.dir_path, fname, ) # load SOLPS plasma and set emission line model self.sim = load_solps_from_mdsplus(mds_server, self.solps_ref_no) self.plasma = self.sim.create_plasma(parent=self.world) self.plasma.atomic_data = OpenADAS(permit_extrapolation=True) emission_line = settings.line[self.line] element, charge, transition = [emission_line[s] for s in ['element', 'charge', 'transition', ]] line_obj = Line(element, charge, transition, ) self._line_excit = ExcitationLine(line_obj, lineshape=StarkBroadenedLine) self._line_recom = RecombinationLine(line_obj, lineshape=StarkBroadenedLine) self.plasma.models = [Bremsstrahlung(), self._line_excit, self._line_recom] wl_0_nm = self._line_excit.atomic_data.wavelength(element, charge, transition, ) self.wl_0 = wl_0_nm * 1e-9 # [m] self.wl_min_nm, self.wl_max_nm = wl_0_nm - 0.2, wl_0_nm + 0.2 # [m] # ugly, but I want to convert the density units to 10^{20} m^{-3} def get_ne(x, y, z, ): return 1e-20 * self.plasma.electron_distribution.density(x, y, z, ) def get_ni(x, y, z, ): return 1e-20 * self.plasma.composition.get(deuterium, 0).distribution.density(x, y, z, ) def get_b_field_mag(x, y, z, ): """ magnitude of the magnetic field at x, y, z :param x: :param y: :param z: :return: """ return self.plasma.b_field(x, y, z, ).length def get_emiss_excit(x, y, z, ): return self._line_excit.emission(Point3D(x, y, z, ), Vector3D(1, 1, 1), Spectrum(380, 700, 100)).total() def get_emiss_recom(x, y, z, ): return self._line_recom.emission(Point3D(x, y, z, ), Vector3D(1, 1, 1), Spectrum(380, 700, 100)).total() self.valid_param_get_fns = {'ne': get_ne, 'ni': get_ni, 'te': self.plasma.electron_distribution.effective_temperature, 'ti': self.plasma.composition.get(deuterium, 0).distribution.effective_temperature, 'tn': self.plasma.composition.get(deuterium, 1).distribution.effective_temperature, 'b_field_mag': get_b_field_mag, 'emiss_excit': get_emiss_excit, 'emiss_recom': get_emiss_recom, } self.valid_params = list(self.valid_param_get_fns.keys()) # load / make the cherab image if os.path.isdir(self.dir_path) and self.overwrite is False: if os.path.isfile(self.fpath) and os.path.isfile(self.fpath_ds): pass else: if not os.path.isdir(self.dir_path): os.mkdir(self.dir_path) self.make_cherab_image() ds, ds_ds = self.load_cherab_image() self.spectral_radiance = ds['spectral_radiance'] self.radiance = self.spectral_radiance.integrate(dim='wavelength') self.radiance = xr.where(xr.ufuncs.isnan(self.radiance), 0, self.radiance, ) self.spectral_radiance_ds = ds_ds['spectral_radiance_ds'] self.radiance_ds = ds_ds['radiance_ds'] self.view_vectors = ds_ds['view_vectors_ds'] self.ray_lengths = ds_ds['ray_lengths_ds'] ds.close()
class CherabMASTU(object): """ demo class for modelling Cherab images of MAST-U """ def __init__(self, solps_ref_no, view, line, camera, optics='MAST_CI_mod', cherab_down_sample=50, verbose=True, display=False, overwrite=False): """ :param solps_ref_no: int :param view: str :param line: str :param camera: str :param optics: str :param cherab_down_sample: int downsample the image by ths factor in both dimensions, for speed / testing. :param verbose: bool :param display: bool :param overwrite: bool """ self.world = World() self.solps_ref_no = solps_ref_no self.line = line self.view = view self.camera = camera self.optics = optics self.cherab_down_sample = cherab_down_sample self.verbose = verbose self.display = display self.overwrite = overwrite self.radiance = NotImplemented self.spectral_radiance = NotImplemented self.pupil_point = settings.view[self.view]['pupil_point'] self.view_vector = settings.view[self.view]['view_vector'] self.sensor_format = settings.camera[self.camera]['sensor_format'] for s in self.sensor_format: assert s % cherab_down_sample == 0 self.sensor_format_ds = tuple((np.array(self.sensor_format) / cherab_down_sample).astype(np.int)) self.pixel_size = settings.camera[self.camera]['pixel_size'] self.pixel_size_ds = self.pixel_size * cherab_down_sample self.x, self.y, = self.calc_pixel_position(self.pixel_size, self.sensor_format) self.x_pixel = self.x.x_pixel self.y_pixel = self.y.y_pixel self.x_ds = self.x.isel(x=slice(0, self.sensor_format[0], cherab_down_sample, )) self.y_ds = self.y.isel(y=slice(0, self.sensor_format[1], cherab_down_sample, )) self.x_pixel_ds = self.x_ds.x_pixel self.y_pixel_ds = self.y_ds.y_pixel self.chunks = {'x': 800, 'y': 800} # calculate field of view (FOV) (horizontal) using sensor geometry and lens focal lengths f_1, f_2, f_3 = settings.optics[self.optics] sensor_dim = self.sensor_format[0] * self.pixel_size self.fov = 2 * np.arctan((sensor_dim / 2) * f_2 / (f_3 * f_1)) * 180 / np.pi # deg # # file and directory paths self.dir_name = str(solps_ref_no) + '_' + view + '_' + line + '_' + camera self.dir_path = os.path.join(path_saved_data, self.dir_name) fname = 'spec_power.nc' fname_ds = 'spec_power_ds.nc' self.fpath_ds = os.path.join(self.dir_path, fname_ds, ) self.fpath = os.path.join(self.dir_path, fname, ) # load SOLPS plasma and set emission line model self.sim = load_solps_from_mdsplus(mds_server, self.solps_ref_no) self.plasma = self.sim.create_plasma(parent=self.world) self.plasma.atomic_data = OpenADAS(permit_extrapolation=True) emission_line = settings.line[self.line] element, charge, transition = [emission_line[s] for s in ['element', 'charge', 'transition', ]] line_obj = Line(element, charge, transition, ) self._line_excit = ExcitationLine(line_obj, lineshape=StarkBroadenedLine) self._line_recom = RecombinationLine(line_obj, lineshape=StarkBroadenedLine) self.plasma.models = [Bremsstrahlung(), self._line_excit, self._line_recom] wl_0_nm = self._line_excit.atomic_data.wavelength(element, charge, transition, ) self.wl_0 = wl_0_nm * 1e-9 # [m] self.wl_min_nm, self.wl_max_nm = wl_0_nm - 0.2, wl_0_nm + 0.2 # [m] # ugly, but I want to convert the density units to 10^{20} m^{-3} def get_ne(x, y, z, ): return 1e-20 * self.plasma.electron_distribution.density(x, y, z, ) def get_ni(x, y, z, ): return 1e-20 * self.plasma.composition.get(deuterium, 0).distribution.density(x, y, z, ) def get_b_field_mag(x, y, z, ): """ magnitude of the magnetic field at x, y, z :param x: :param y: :param z: :return: """ return self.plasma.b_field(x, y, z, ).length def get_emiss_excit(x, y, z, ): return self._line_excit.emission(Point3D(x, y, z, ), Vector3D(1, 1, 1), Spectrum(380, 700, 100)).total() def get_emiss_recom(x, y, z, ): return self._line_recom.emission(Point3D(x, y, z, ), Vector3D(1, 1, 1), Spectrum(380, 700, 100)).total() self.valid_param_get_fns = {'ne': get_ne, 'ni': get_ni, 'te': self.plasma.electron_distribution.effective_temperature, 'ti': self.plasma.composition.get(deuterium, 0).distribution.effective_temperature, 'tn': self.plasma.composition.get(deuterium, 1).distribution.effective_temperature, 'b_field_mag': get_b_field_mag, 'emiss_excit': get_emiss_excit, 'emiss_recom': get_emiss_recom, } self.valid_params = list(self.valid_param_get_fns.keys()) # load / make the cherab image if os.path.isdir(self.dir_path) and self.overwrite is False: if os.path.isfile(self.fpath) and os.path.isfile(self.fpath_ds): pass else: if not os.path.isdir(self.dir_path): os.mkdir(self.dir_path) self.make_cherab_image() ds, ds_ds = self.load_cherab_image() self.spectral_radiance = ds['spectral_radiance'] self.radiance = self.spectral_radiance.integrate(dim='wavelength') self.radiance = xr.where(xr.ufuncs.isnan(self.radiance), 0, self.radiance, ) self.spectral_radiance_ds = ds_ds['spectral_radiance_ds'] self.radiance_ds = ds_ds['radiance_ds'] self.view_vectors = ds_ds['view_vectors_ds'] self.ray_lengths = ds_ds['ray_lengths_ds'] ds.close() # self.mask_ds = self.make_mask_ds() def load_cherab_image(self): ds = xr.open_dataset(self.fpath, chunks=self.chunks) ds_ds = xr.load_dataset(self.fpath_ds, ) return ds, ds_ds, def make_cherab_image(self): """ run cherab to generate the synthetic spectral cube :return: """ if self.radiance is not NotImplemented: self.radiance.close() if self.spectral_radiance is not NotImplemented: self.spectral_radiance.close() import_mastu_mesh(self.world, ) # first, define camera, calculate view vectors and calculate ray lengths pipeline_spectral = SpectralPowerPipeline2D() pipeline_spectral_rad = SpectralRadiancePipeline2D() pipelines = [pipeline_spectral, pipeline_spectral_rad, ] camera = PinholeCamera(self.sensor_format_ds, fov=self.fov, pipelines=pipelines, parent=self.world) # orient and position the camera init_view_vector, init_up_vector = Vector3D(0, 0, 1), Vector3D(0, 1, 0) axle_1 = init_view_vector.cross(self.view_vector) angle = init_view_vector.angle(self.view_vector) t_1 = rotate_vector(angle, axle_1) final_up_vector = rotate_vector(-90, axle_1) * self.view_vector intermediate_up_vector = t_1 * init_up_vector angle_between = intermediate_up_vector.angle(final_up_vector) t_2 = rotate_vector(-angle_between, self.view_vector) camera.transform = translate(self.pupil_point[0], self.pupil_point[1], self.pupil_point[2], ) * t_2 * t_1 vector_xyz = np.arange(3) vector_xyz = xr.DataArray(vector_xyz, coords=(vector_xyz, ), dims=('vector_xyz',), name='vector_xyz', ) # calculating the pixel view directions view_vectors = xr.combine_nested( [xr.zeros_like(self.x_pixel_ds + self.y_pixel_ds) + self.view_vector[i] for i in [0, 1, 2, ]], concat_dim=(vector_xyz,), ) view_vectors = view_vectors.rename('view_vectors') def v3d2da(v3d): """ raysect Vector3D to xarray DataArray :param v3d: :return: """ da = np.array([v3d.x, v3d.y, v3d.z, ]) da = xr.DataArray(da, coords=(np.arange(3),), dims=('vector_xyz',), ) return da # basis unit vectors defining camera view -- v_z is forward and v_y is up v_y = final_up_vector.normalise() v_x = self.view_vector.cross(v_y).normalise() v_z = self.view_vector.normalise() v_x, v_y, v_z = [v3d2da(i) for i in [v_x, v_y, v_z, ]] # FOV defines the widest view, with pixels defined as square. sensor_aspect = self.sensor_format[1] / self.sensor_format[0] if sensor_aspect > 1: fov_v = self.fov fov_h = self.fov / sensor_aspect elif sensor_aspect == 1: fov_v = fov_h = self.fov elif sensor_aspect < 1: fov_h = self.fov fov_v = self.fov * sensor_aspect else: raise Exception() pixel_projection = 2 * np.tan(fov_h * np.pi / 360) / self.sensor_format[0] view_vectors = view_vectors + (v_x * (self.x_pixel_ds - self.sensor_format[0] / 2 + 0.5) * pixel_projection) + \ (v_y * (self.y_pixel_ds - self.sensor_format[1] / 2 + 0.5) * pixel_projection) if self.verbose: print('--status: calculating ray lengths') # TODO there has to be a better way of doing this?! ray_lengths = xr.DataArray(np.zeros(self.sensor_format_ds), dims=('x', 'y', ), coords=(self.x_ds, self.y_ds, )) for idx_x, x_pixel in enumerate(self.x_pixel_ds.values): if self.verbose and idx_x % 10 == 0: print('x =', str(x_pixel)) for idx_y, y_pixel in enumerate(self.y_pixel_ds.values): direction = Vector3D(*list(view_vectors.isel(x=idx_x, y=idx_y, ).values)) intersections = [] for p in self.world.primitives: intersection = p.hit(CoreRay(self.pupil_point, direction, )) if intersection is not None: intersections.append(intersection) # find the intersection corresponding to the shortest ray length no_intersections = len(intersections) if no_intersections == 0: ray_lengths.values[idx_x, idx_y] = 3 else: ray_lengths.values[idx_x, idx_y] = min([i.ray_distance for i in intersections if i.primitive.name != 'Plasma Geometry']) camera.spectral_bins = 40 camera.pixel_samples = 10 camera.min_wavelength = self.wl_min_nm camera.max_wavelength = self.wl_max_nm camera.quiet = not self.verbose camera.observe() # output to netCDF via xarray wl = pipeline_spectral.wavelengths wl = xr.DataArray(wl, coords=(wl, ), dims=('wavelength', )) * 1e-9 # ( m ) spec_power_ds = pipeline_spectral.frame.mean * 1e9 # converting units from (W/nm) --> (W/m) spec_radiance_ds = pipeline_spectral_rad.frame.mean * 1e9 coords = (self.x_ds, self.y_ds, wl, ) dims = ('x', 'y', 'wavelength', ) name = 'spec_power' attrs = {'units': 'W/m^2/str/m'} spec_power_ds = xr.DataArray(np.flip(spec_power_ds, axis=1), coords=coords, dims=dims, name=name, attrs=attrs, ) spec_radiance_ds = xr.DataArray(np.flip(spec_radiance_ds, axis=1, ), coords=coords, dims=dims, name=name, attrs=attrs, ) # calculate the centre-of-mass wavelength radiance_ds = spec_power_ds.integrate(dim='wavelength').assign_attrs({'units': 'W/m^2/str', }) ds_ds = xr.Dataset({'spectral_radiance_ds': spec_radiance_ds, 'radiance_ds': radiance_ds, 'view_vectors_ds': view_vectors, 'ray_lengths_ds': ray_lengths }) x_p_y = self.x + self.y spec_power = spec_power_ds.interp_like(x_p_y) / self.cherab_down_sample # to conserve power ds = xr.Dataset({'spectral_radiance': spec_power, }) ds_ds.to_netcdf(self.fpath_ds, mode='w', ) ds.to_netcdf(self.fpath, mode='w', ) def plot_line_of_sight(self, x_pixel, y_pixel, ax, **kwargs): """ :param x_pixel: :param y_pixel: :param ax: :return: """ direction = Vector3D(*list(self.view_vectors.isel(x=x_pixel, y=y_pixel, ).values)).normalise() ray_length = float(self.ray_lengths.isel(x=x_pixel, y=y_pixel, ).values) n_steps = 50 increment = (ray_length / n_steps) * direction rs, zs = np.zeros(n_steps), np.zeros(n_steps) point_i = self.pupil_point # initialise at pupil for i in range(n_steps): point_i += increment rs[i], zs[i], _ = cart2cyl(*[point_i[j] for j in range(3)]) ax.plot(rs, zs, **kwargs) def calc_pixel_position(self, pixel_size, sensor_format, ): """ Calculate pixel positions (in m) on the camera's sensor plane (the x-y plane). The origin of the x-y coordinate system is the centre of the sensor. Pixel positions correspond to the pixel centres. If x_pixel and y_pixel are specified then only returns the position of that pixel. :param float pixel_size: in m :param tuple sensor_format: (num_pix_x, num_pix_y) :return: """ centre_pos = pixel_size * np.array(sensor_format) / 2 x = (np.arange(sensor_format[0]) + 0.5) * pixel_size - centre_pos[0] y = (np.arange(sensor_format[1]) + 0.5) * pixel_size - centre_pos[1] x = xr.DataArray(x, dims=('x',), coords=(x,), ) y = xr.DataArray(y, dims=('y',), coords=(y,), ) x_pixel_coord = xr.DataArray(np.arange(sensor_format[0], ), dims=('x',), coords=(x,), ) y_pixel_coord = xr.DataArray(np.arange(sensor_format[1], ), dims=('y',), coords=(y,), ) x = x.assign_coords({'x_pixel': ('x', x_pixel_coord), }, ) y = y.assign_coords({'y_pixel': ('y', y_pixel_coord), }, ) return x, y
spectrum = self.recom.emission(point, X_VECTOR, spectrum) return spectrum.total() world = World() edge2d_sim = load_edge2d_from_eproc( '/home/jsimpson/cmg/catalog/edge2d/jet/85274/aug0717/seq#23/tran') plasma = edge2d_sim.create_plasma(parent=world) plasma.atomic_data = OpenADAS(permit_extrapolation=True) # Pick emission models d_alpha = Line(deuterium, 0, (3, 2)) d_alpha_exc = ExcitationLine(d_alpha) d_alpha_recom = RecombinationLine(d_alpha) plasma.models = [d_alpha_exc, d_alpha_recom] emission_function = PythonFunction3D( SimpleEmissionFunction(d_alpha_exc, d_alpha_recom, (650, 660, 1))) voxel_grid = load_kl11_voxel_grid() voxel_emissivities = voxel_grid.emissivities_from_function(emission_function) voxel_grid.plot(voxel_values=voxel_emissivities) plt.xlim(2.3, 3.0) plt.ylim(-1.8, -1.2) # time_a = time.time() # sensitivity = load_kl11_sensitivity_matrix() # print('Time to load sensitivity matrix => ', (time.time() - time_a) / 60) # forward_image = np.matmul(sensitivity, emission_grid.emissivities) #
plasma.composition = [d0_species, d1_species, n1_species] # setup the Balmer lines hydrogen_I_410 = Line(deuterium, 0, (6, 2)) # n = 6->2: 410.12nm hydrogen_I_396 = Line(deuterium, 0, (7, 2)) # n = 7->2: 396.95nm # setup the Nitrgon II line with multiplet splitting instructions nitrogen_II_404 = Line(nitrogen, 1, ("2s2 2p1 4f1 3G13.0", "2s2 2p1 3d1 3F10.0")) multiplet = [[403.509, 404.132, 404.354, 404.479, 405.692], [0.205, 0.562, 0.175, 0.029, 0.029]] # add all lines to the plasma plasma.models = [ ExcitationLine(hydrogen_I_410), RecombinationLine(hydrogen_I_410), ExcitationLine(hydrogen_I_396), RecombinationLine(hydrogen_I_396), ExcitationLine(nitrogen_II_404, lineshape=MultipletLineShape, lineshape_args=[multiplet]), ] # Ray-trace and plot the results plt.ioff() r = Ray(origin=Point3D(0, 0, -5), direction=Vector3D(0, 0, 1), min_wavelength=395, max_wavelength=415, bins=1000) s = r.trace(world)