from nbtemplate import display_header
display_header('3Dview.ipynb')
Last revision in version control:
This document is git version controlled. The repository is available at https://github.com/hamogu/arcus. See git commit log for full revision history.
Code was last run with:
The lightpath in Arcus is simple in principle (mirror - grating - detector) but the fact that Arcus has four independent channels and that in each channel, there are a number of SPOs and detectors makes it hard to visualize all components. To help understand the layout better, I show a number of interactive 3D visualizations of Arcus here. Those visualizations are based on the same code that I use to make the quantitative predictions, but certain parameters like the number of rays are tuned here to make instructive and visually appealing simulations.
All the 3D views below are interactive. They can be rotated, panned, and zoomed with the different mouse in all supported browsers; for trackpad users hold down CTRL or ALT for pan and zoom. Pressing "r" on the keyboard when the mouse is on a view returns that particular view to the initial position. See the X3DOM documentation for a full list of supported mouse and keyboard commands.
import warnings
import numpy as np
import astropy.units as u
from x3d import x3d
from marxs import simulator
from marxs.visualization.x3d import plot_object, plot_rays
from marxs.missions.arcus.arcus import ArcusForPlot
from marxs.missions.arcus import boom
from marxs.missions.arcus.defaults import DefaultSource, DefaultPointing
Rays start in the aperture, which consists of four rectangles located above the SPO channels. Each channel has a number of SPO modules, shown in green. Photons bounce off the mirrors twice in a Wolter type I geometry. However, in this simulation the SPOs are somewhat simplified such that the reflection actually happens in a single plane. Behind the SPOs are the CAT gratings (white). For each channel the gratings are arranged to follow the shape of the Rowland torus. This can been seen best when the figure is rotated to look at the "side" of the arrangement. CAT gratings are slightly tilted such that the photons hit the gratings bars on the "side", but this blaze angle is < 2 degrees and is hard to see by eye. SPOs and gratings are held by a support structure in the forward assembly, which is not shown. The forward assembly and the focal plane are connected by an extensible boom (black). Some SPOs are located outside the boom, and the light needs to pass though the sides of the boom, as shown in the boom study. Detectors (yellow) are again arranged on the surface of the Rowland torus, zooming in on the detectors shows that they follow a circle.
Note that the Rowland torus for each channel is slightly different, see the Rowland torus specifications for details.
The figure shows a ray-trace for an on-axis point source with monochromatic emission at 0.5 keV = 24.8 Å. Arcus has four channels positioned in two pairs. The optical axes are different for each channel to reduce the impact of chip gaps. Two channels disperse left to right, the other two right to left, also shown in the explainatory images of the signal on the detector. In the simulation, the bundle of rays from each channel forms a separate trace on the detectors, rays from different channels do not mix. Rays are colored by channel, i.e. all rays in the same channel have have the same color.
from marxs.missions.arcus.arcus import defaultconf
src = DefaultSource(energy=0.5 * u.keV)
pnt = DefaultPointing()
instrument = ArcusForPlot(conf=defaultconf)
keeppos = simulator.KeepCol('pos')
instrument.postprocess_steps = [keeppos]
photons = src.generate_photons(10000 * u.s)
photons = pnt(photons)
photons = instrument(photons)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
out = plot_object(instrument)
pos = keeppos.format_positions()
ind = (photons['probability'] > 1e-3) & (photons['CCD'] >= 0)
out = plot_rays(pos[ind, :, :], scalar=photons['order'][ind], scene=out)
out.children.append(x3d.Viewpoint(description='Overview ', orientation=(.5, .3, .3, -.3), viewAll=True))
out.children.append(x3d.Viewpoint(description='Camera', position=(-700, 50, 500),
orientation=(-0., -0.6, -0., 0.3)
))
out