### Compile and install batoid from source Source: https://jmeyers314.github.io/batoid/overview.html Compile and install batoid from the cloned repository. Optionally install to the user's local site-packages. ```bash python setup.py install ``` ```bash python setup.py install --user ``` -------------------------------- ### Install batoid from PyPI Source: https://jmeyers314.github.io/batoid/overview.html Install the released version of batoid from PyPI. Requires a C++14 compiler that setup.py can find. ```bash pip install batoid ``` -------------------------------- ### Install batoid testing requirements Source: https://jmeyers314.github.io/batoid/overview.html Install the testing requirements for batoid from the test_requirements.txt file. ```bash pip install -r test_requirements.txt ``` -------------------------------- ### SimpleCoating(reflectivity, transmissivity) Source: https://jmeyers314.github.io/batoid/_modules/batoid/coating.html Constructor for SimpleCoating, a coating with constant reflectivity and transmissivity. ```APIDOC ## SimpleCoating(reflectivity, transmissivity) ### Description Creates a SimpleCoating instance with constant reflectivity and transmissivity. ### Method Constructor ### Endpoint SimpleCoating.__init__ ### Parameters - **reflectivity** (float) - Required - Reflection coefficient. - **transmissivity** (float) - Required - Transmission coefficient. ``` -------------------------------- ### Verify equivalent obscuration behavior for ObscIntersection Source: https://jmeyers314.github.io/batoid/obscurations.html Shows that annulus and alternate_annulus produce the same obscuring behavior, even though they do not compare equal. The example creates a grid of rays and compares the obscured ray vectors. ```python >>> rays = batoid.RayVector.asGrid( backDist=10.0, wavelength=500e-9, nx=10, lx=4.0, dirCos=(0,0,1) ) >>> obsc1 = annulus.obscure(rays) >>> obsc2 = alternate_annulus.obscure(rays) >>> obsc1 == obsc2 True ``` -------------------------------- ### SellmeierMedium.__init__ Source: https://jmeyers314.github.io/batoid/_modules/batoid/medium.html Constructor for a medium with Sellmeier dispersion formula. ```APIDOC ## SellmeierMedium.__init__(*args, **kwargs) ### Description Initializes a medium with Sellmeier dispersion formula. The Sellmeier formula is n = sqrt(1 + sum_{i=1}^3 (B_i * lambda^2) / (lambda^2 - C_i)), where lambda is the vacuum wavelength in microns. ### Parameters - **coefs** (array of float) - Required - Sellmeier coefficients (B1, B2, B3, C1, C2, C3). Can be passed as six positional arguments, a single array, or keyword arguments B1, B2, B3, C1, C2, C3. ``` -------------------------------- ### Verify equivalent obscuration behavior for ObscUnion Source: https://jmeyers314.github.io/batoid/obscurations.html Shows that big_circle and alternate_big_circle produce the same obscuring behavior, even though they do not compare equal. The example creates a grid of rays and compares the obscured ray vectors. ```python >>> rays = batoid.RayVector.asGrid( backDist=10.0, wavelength=500e-9, nx=10, lx=4.0, dirCos=(0,0,1) ) >>> obsc1 = big_circle.obscure(rays) >>> obsc2 = alternate_big_circle.obscure(rays) >>> obsc1 == obsc2 True ``` -------------------------------- ### Interface.__init__ Source: https://jmeyers314.github.io/batoid/_modules/batoid/optic.html Initializes an Interface instance, an Optic representing a single surface. The surface and optional obscuration are set, and the path is initialized to the optic's name. ```APIDOC ## Interface.__init__ ### Description Initializes an Interface instance, an Optic representing a single surface. The surface and optional obscuration are set, and the path is initialized to the optic's name. ### Method Constructor ### Signature Interface(surface, obscuration=None, **kwargs) ### Parameters - **surface** (batoid.Surface) - The surface instance for this Interface. - **obscuration** (batoid.Obscuration, optional) - Obscuration instance indicating which x,y coordinates are obscured/unobscured for rays intersecting this optic. Default: None (no ray obscuration). - **kwargs** - Other parameters to forward to Optic.__init__. ### Returns None ``` -------------------------------- ### TableMedium.__init__ Source: https://jmeyers314.github.io/batoid/_modules/batoid/medium.html Constructor for a medium with refractive index defined via a lookup table. ```APIDOC ## TableMedium.__init__(wavelengths, ns) ### Description Initializes a medium with refractive index defined via a lookup table. ### Parameters - **wavelengths** (array of float) - Required - Wavelengths in meters. - **ns** (array of float) - Required - Refractive indices. ``` -------------------------------- ### Create and compare ObscIntersection Source: https://jmeyers314.github.io/batoid/_modules/batoid/obscuration.html Demonstrates creating an ObscIntersection using individual arguments or a list, and verifying that different representations produce the same obscuration behavior. ```python >>> big_circle = batoid.ObscCircle(2.0) >>> small_circle = batoid.ObscCircle(1.0) >>> annulus = batoid.ObscAnnulus(1.0, 2.0) >>> alternate_annulus = batoid.ObscIntersection( batoid.ObscNegation(small_circle), big_circle ) ``` ```python >>> other_alternate_annulus = batoid.ObscIntersection([ batoid.ObscNegation(small_circle), big_circle ]) ``` ```python >>> rays = batoid.RayVector.asGrid( backDist=10.0, wavelength=500e-9, nx=10, lx=4.0, dirCos=(0,0,1) ) >>> obsc1 = annulus.obscure(rays) >>> obsc2 = alternate_annulus.obscure(rays) >>> obsc1 == obsc2 True ``` -------------------------------- ### Optic.__init__ Source: https://jmeyers314.github.io/batoid/_modules/batoid/optic.html Initializes an Optic instance with optional name, coordinate system, input/output media, skip flag, and additional attributes. ```APIDOC ## Optic.__init__ ### Description Initializes an Optic instance, the base class for all batoid optics and optical systems. Sets the name, coordinate system, input/output media, skip flag, and any additional attributes. ### Method Constructor ### Signature Optic(name=None, coordSys=globalCoordSys, inMedium=vacuum, outMedium=vacuum, skip=False, **kwargs) ### Parameters - **name** (str, optional) - Name for this optic. - **coordSys** (batoid.CoordSys, optional) - Coordinate system indicating position and orientation of the optic's vertex with respect to the global coordinate system. Default: global coordinate system. - **inMedium** (batoid.Medium, optional) - Medium in which approaching rays reside. Default: vacuum. - **outMedium** (batoid.Medium, optional) - Medium in which rays will leave this optic. Default: vacuum. - **skip** (bool, optional) - Whether to skip this optic when tracing. Default: False. - **kwargs** - Other attributes to add as object attributes. ### Returns None ``` -------------------------------- ### TableMedium.fromTxt(filename, **kwargs) Source: https://jmeyers314.github.io/batoid/media.html Loads a text file with refractive index information. The file should have two columns: wavelength in microns and corresponding refractive indices. ```APIDOC ## TableMedium.fromTxt(filename, **kwargs) ### Description Loads a text file with refractive index information. The file should have two columns: wavelength in microns and corresponding refractive indices. ### Parameters - **filename** (string) - Required - Path to the text file. - **kwargs** - Optional - Additional keyword arguments. ``` -------------------------------- ### batoid.SimpleCoating Source: https://jmeyers314.github.io/batoid/_sources/coatings.rst.txt Documentation for the SimpleCoating class, including its members and inheritance. ```APIDOC ## batoid.SimpleCoating ### Description A simple coating class in batoid, inheriting from Coating. ### Inheritance - Inherits from: batoid.Coating ### Members - (Members are documented via autoclass directive; no explicit members listed in source.) ``` -------------------------------- ### SumitaMedium Class Implementation Source: https://jmeyers314.github.io/batoid/_modules/batoid/medium.html The SumitaMedium class handles optical media defined by Sumita coefficients. It supports initialization via positional arguments or keyword arguments. ```python def __init__(self, *args, **kwargs): if len(args) == 6: coefs = tuple(args) elif len(args) == 1: coefs = tuple(args[0]) elif kwargs: coefs = tuple([ kwargs[k] for k in ['A0', 'A1', 'A2', 'A3', 'A4', 'A5'] ]) else: raise ValueError("Incorrect number of arguments") self.coefs = coefs self._medium = _batoid.CPPSumitaMedium(*coefs) def __eq__(self, rhs): if type(rhs) == type(self): return self.coefs == rhs.coefs return False def __getstate__(self): return self.coefs def __setstate__(self, coefs): self.coefs = coefs self._medium = _batoid.CPPSumitaMedium(*coefs) def __hash__(self): return hash(("batoid.SumitaMedium", self.coefs)) def __repr__(self): return f"SumitaMedium({self.coefs})" ``` -------------------------------- ### _fromStop Source: https://jmeyers314.github.io/batoid/rays.html Creates rays that intersect the stop surface at given points. The algorithm places rays on the stop surface and backs them up to be in front of any surfaces of the optic. ```APIDOC ## _fromStop ### Description Creates rays that intersect the stop surface at given points. The algorithm places rays on the stop surface and backs them up to be in front of any surfaces of the optic. ### Method _fromStop ### Parameters - **x** (float) - x-coordinate of the intersection point on the stop surface. - **y** (float) - y-coordinate of the intersection point on the stop surface. - **optic** (batoid.Optic, optional) - Optic to extract values for backDist, medium, stopSurface, and outer. - **backDist** (float, optional) - Distance to back up rays from the stop surface. - **medium** (batoid.Medium, optional) - Initial medium of each ray. - **stopSurface** (batoid.Interface, optional) - Surface defining the system stop. - **coordSys** (optional) - Coordinate system for the rays. - **wavelength** (float, optional) - Vacuum wavelength of rays in meters. - **source** (None or ndarray of float, shape (3,), optional) - Where rays originate. - **dirCos** (ndarray of float, shape (3,), optional) - Initial direction of propagation. - **theta_x, theta_y** (float, optional) - Field angle in radians. - **projection** (str, optional) - Projection used to convert field angle to direction cosines. Default is 'postel'. - **flux** (float, optional) - Flux to assign each ray. Default is 1. ``` -------------------------------- ### Create and compare ObscUnion Source: https://jmeyers314.github.io/batoid/_modules/batoid/obscuration.html Demonstrates creating an ObscUnion using a list or tuple and verifying that different representations produce the same obscuration behavior on a RayVector. ```python >>> other_alternate_big_circle = batoid.ObscUnion([small_circle, annulus]) ``` ```python >>> rays = batoid.RayVector.asGrid( backDist=10.0, wavelength=500e-9, nx=10, lx=4.0, dirCos=(0,0,1) ) >>> obsc1 = big_circle.obscure(rays) >>> obsc2 = alternate_big_circle.obscure(rays) >>> obsc1 == obsc2 True ``` -------------------------------- ### Sum.__init__ Source: https://jmeyers314.github.io/batoid/_modules/batoid/surface.html Initializes a Sum surface with a list of Surface objects. The surfaces are stored as a tuple and a C++ object is created for the composite surface. ```APIDOC ## Sum.__init__ ### Description Initializes a Sum surface with a list of Surface objects. The surfaces are stored as a tuple and a C++ object is created for the composite surface. ### Parameters - **surfaces** (list of Surface) - Required - The surfaces to add together. ### Example ```python sum_surface = Sum([surface1, surface2]) ``` ``` -------------------------------- ### Optic.fromYaml(filename) Source: https://jmeyers314.github.io/batoid/optic.html Loads an Optic (commonly a complete telescope) from a YAML file. This is the most common way to create an Optic. ```APIDOC ## Optic.fromYaml(filename) ### Description Load an Optic (commonly a complete telescope) from the given yaml file. This is the most common way to create an Optic. If the file is not initially found, then look in the batoid.datadir directory and subdirectories for the first matching filename and use that. ### Method classmethod ### Parameters - **filename** (str) - Required - Name of yaml file to load ### Returns Optic ``` -------------------------------- ### Air(pressure=69.328, temperature=293.15, h2o_pressure=1.067) Source: https://jmeyers314.github.io/batoid/media.html Creates a Medium for air with configurable atmospheric conditions. ```APIDOC ## Air(pressure=69.328, temperature=293.15, h2o_pressure=1.067) ### Description Creates a Medium for air. Uses formulae from Filippenko (1982), Edlen (1953), and Coleman, Bozman, and Meggers (1960). ### Parameters - **pressure** (float, optional) - Atmospheric pressure in kiloPascals. Default: 69.328. - **temperature** (float, optional) - Temperature in Kelvin. Default: 293.15. - **h2o_pressure** (float, optional) - Water vapor pressure in kiloPascals. Default: 1.067. ``` -------------------------------- ### Quadric Surface State and Equality Methods Source: https://jmeyers314.github.io/batoid/_modules/batoid/surface.html Implementation of state management and equality comparison for the Quadric surface class. ```python def __setstate__(self, args): self.__init__(*args) def __getstate__(self): return (self.R, self.conic) def __eq__(self, rhs): if not isinstance(rhs, Quadric): return False return (self.R == rhs.R and self.conic == rhs.conic) def __repr__(self): return f"Quadric({self.R}, {self.conic})" ``` -------------------------------- ### Interface.traceFull() Source: https://jmeyers314.github.io/batoid/optic.html Traces rays through the interface and returns full ray data. This method is listed in the documentation but no additional details are provided. ```APIDOC ## Interface.traceFull() ### Description Trace rays through this interface and return full ray data. No additional details are provided in the source documentation. ``` -------------------------------- ### RayVector initialization logic Source: https://jmeyers314.github.io/batoid/_modules/batoid/rayVector.html Internal logic for processing ray initialization parameters, including handling of optic defaults, coordinate transformations, and wavelength settings. ```python from .optic import Interface from .surface import Plane if optic is not None: if backDist is None: backDist = optic.backDist if medium is None: medium = optic.inMedium if stopSurface is None: stopSurface = optic.stopSurface if coordSys is None: coordSys = optic.coordSys if backDist is None: backDist = 40.0 if stopSurface is None: stopSurface = Interface(Plane()) if medium is None: medium = vacuum if coordSys is None: coordSys = globalCoordSys if dirCos is None and source is None: dirCos = fieldToDirCos(theta_x, theta_y, projection=projection) if wavelength is None: raise ValueError("Missing wavelength keyword") x = np.atleast_1d(x).astype(float, copy=False) y = np.atleast_1d(y).astype(float, copy=False) z = stopSurface.surface.sag(x, y) transform = CoordTransform(stopSurface.coordSys, coordSys) applyForwardTransformArrays(transform, x, y, z) w = np.empty_like(x) w.fill(wavelength) n = medium.getN(wavelength) return cls._finish( backDist, source, dirCos, n, x, y, z, w, flux, coordSys ) ``` -------------------------------- ### Synchronization methods Source: https://jmeyers314.github.io/batoid/_modules/batoid/rayVector.html Methods to synchronize ray data between host and device. ```python def _syncToHost(self): if "_rv" not in self.__dict__: # Was never copied to device, so still synchronized. return self._rv.x.syncToHost() self._rv.y.syncToHost() self._rv.z.syncToHost() self._rv.vx.syncToHost() self._rv.vy.syncToHost() self._rv.vz.syncToHost() self._rv.t.syncToHost() self._rv.wavelength.syncToHost() self._rv.flux.syncToHost() self._rv.vignetted.syncToHost() self._rv.failed.syncToHost() def _syncToDevice(self): self._rv.x.syncToDevice() self._rv.y.syncToDevice() self._rv.z.syncToDevice() self._rv.vx.syncToDevice() self._rv.vy.syncToDevice() self._rv.vz.syncToDevice() self._rv.t.syncToDevice() self._rv.wavelength.syncToDevice() self._rv.flux.syncToDevice() self._rv.vignetted.syncToDevice() self._rv.failed.syncToDevice() ``` -------------------------------- ### Rays constructor Source: https://jmeyers314.github.io/batoid/rays.html Creates a Rays object with specified parameters for optical ray tracing. Parameters control ray origin, direction, wavelength, sampling grid, and flux. ```APIDOC ## Rays ### Description Creates a Rays object for optical simulations. Parameters control ray origin, direction, wavelength, sampling grid, and flux. ### Parameters - **optic** (batoid.Optic, optional) - If present, try to extract values for backDist, medium, stopSurface, and outer from the Optic. Values explicitly passed to asPolar as keyword arguments override those extracted from optic. - **backDist** (float, optional) - Map rays backwards from the stop surface to the plane that is perpendicular to the ray and backDist meters from the point (0, 0, z(0,0)) on the stop surface. Should generally be large enough that any obscurations or phantom surfaces occurring before the stop surface are now in front of the ray. If None and optic is set, infer from optic.backDist. If both None, default 40 meters. - **medium** (batoid.Medium, optional) - Initial medium of each ray. If None and optic is set, infer from optic.inMedium. If both None, default vacuum. - **stopSurface** (batoid.Interface, optional) - Surface defining the system stop. If None and optic is set, infer from optic.stopSurface. If both None, default Interface(Plane()) which is the global x-y plane. - **wavelength** (float) - Vacuum wavelength of rays in meters. - **outer** (float) - Outer radius of annulus in meters. - **inner** (float, optional) - Inner radius of annulus in meters. Default is 0.0. - **source** (None or ndarray of float, shape (3,), optional) - Where rays originate. If None, rays originate an infinite distance away, in which case dirCos must be specified. If ndarray, rays originate from this point in global coordinates and dirCos is ignored. - **dirCos** (ndarray of float, shape (3,), optional) - If source is None, initial direction of propagation. If source is not None, ignored. Alternative to theta_x, theta_y. - **theta_x, theta_y** (float, optional) - Field angle in radians. If source is None, initial direction of propagation. If source is not None, ignored. Uses utils.fieldToDirCos to convert to direction cosines. Alternative to dirCos. - **projection** ({'postel', 'zemax', 'gnomonic', 'stereographic', 'lambert', 'orthographic'}, optional) - Projection used to convert field angle to direction cosines. - **nrad** (int) - Number of radii on which to create rays. - **naz** (int) - Approximate number of azimuthal angles uniformly spaced along the outermost ring. Each ring constrained to a multiple of 6 azimuths. Inner rings have fewer azimuths in proportion to radius, also multiple of 6. If innermost ring has radius 0, exactly 1 ray used. - **flux** (float, optional) - Flux to assign each ray. Default is 1.0. - **nrandom** (int, optional) - If not None, uniformly sample this many rays from annular region instead of hexapolar grid. - **rng** (None or int or numpy.random.Generator, optional) - Random number generator or seed to use for random sampling. ``` -------------------------------- ### CompoundOptic.traceFull(rv, path=None, reverse=False) Source: https://jmeyers314.github.io/batoid/_modules/batoid/optic.html Traces rays through the CompoundOptic, either through all interfaces in order or along a specified path. Returns a dictionary mapping interface names to dictionaries containing the incoming and outgoing rays at each interface. ```APIDOC ## CompoundOptic.traceFull(rv, path=None, reverse=False) ### Description Traces rays through the CompoundOptic. If path is None, traces through all interfaces in nominal order (or reverse if reverse=True). If path is provided, traces along the specified sequence of interface names, handling reflections at direction changes. Returns a dictionary with entries for each traced interface. ### Parameters - **rv** (RayVector) - Required - Input rays to trace. - **path** (list of str, optional) - Sequence of interface names to trace through. If None, traces through all interfaces. - **reverse** (bool, optional) - If True, trace through the optic in reverse direction. Default: False. ### Returns - **result** (OrderedDict) - Dictionary where keys are interface names with suffixes (e.g., 'name_0', 'name_1') and values are dictionaries with keys 'name' (str), 'in' (RayVector), and 'out' (RayVector). The 'in' and 'out' rays are in the coordinate system of the interface. ### Notes - The coordinate systems of returned rays generally differ from the input coordinate system. Use RayVector.toCoordSys to transform. - When path is provided, reflections occur at direction changes, and obscurations are applied if present. ``` -------------------------------- ### Ray Vector Initialization Logic Source: https://jmeyers314.github.io/batoid/_modules/batoid/rayVector.html Internal logic for calculating ray positions and flux based on rings and spokes, typically used during ray vector construction. ```python if dirCos is None and source is None: dirCos = fieldToDirCos(theta_x, theta_y, projection=projection) if wavelength is None: raise ValueError("Missing wavelength keyword") if isinstance(rings, Integral): if spacing == 'uniform': rings = np.linspace(inner, outer, rings) elif spacing == 'GQ': if spokes is None: spokes = 2*rings+1 Li, w = np.polynomial.legendre.leggauss(rings) eps = inner/outer area = np.pi*(1-eps**2) rings = np.sqrt(eps**2 + (1+Li)*(1-eps**2)/2)*outer flux = w*area/(2*spokes) if isinstance(spokes, Integral): spokes = np.linspace(0, 2*np.pi, spokes, endpoint=False) rings, spokes = np.meshgrid(rings, spokes) flux = np.broadcast_to(flux, rings.shape) rings = rings.ravel() spokes = spokes.ravel() flux = flux.ravel() x = rings*np.cos(spokes) y = rings*np.sin(spokes) del rings, spokes z = stopSurface.surface.sag(x, y) transform = CoordTransform(stopSurface.coordSys, coordSys) applyForwardTransformArrays(transform, x, y, z) w = np.empty_like(x) w.fill(wavelength) n = medium.getN(wavelength) return cls._finish( backDist, source, dirCos, n, x, y, z, w, flux, coordSys ) ``` -------------------------------- ### spot(optic, theta_x, theta_y, wavelength, projection='postel', nx=32, reference='chief') Source: https://jmeyers314.github.io/batoid/_modules/batoid/analysis.html Computes the spot diagram of an optical system at a given field angle and wavelength. Returns the x and y coordinates of non-vignetted rays in the focal plane. ```APIDOC ## spot(optic, theta_x, theta_y, wavelength, projection='postel', nx=32, reference='chief') ### Description Computes the spot diagram of an optical system at a given field angle and wavelength. Returns the x and y coordinates of non-vignetted rays in the focal plane. ### Parameters - **optic** (batoid.Optic) - Required - Optical system - **theta_x** (float) - Required - Field angle in radians - **theta_y** (float) - Required - Field angle in radians - **wavelength** (float) - Required - Wavelength in meters - **projection** (string) - Optional - Projection used to convert field angle to direction cosines. Options: 'postel', 'zemax', 'gnomonic', 'stereographic', 'lambert', 'orthographic'. Default: 'postel' - **nx** (int) - Optional - Size of ray grid to use. Default: 32 - **reference** (string) - Optional - If 'chief', then center the output lattice where the chief ray intersects the focal plane. If 'mean', then center at the mean non-vignetted ray intersections. Options: 'chief', 'mean'. Default: 'chief' ### Returns - **x** (array) - x coordinates of non-vignetted rays - **y** (array) - y coordinates of non-vignetted rays ``` -------------------------------- ### Recursively trace rays with traceSplit Source: https://jmeyers314.github.io/batoid/_modules/batoid/optic.html Recursively traces rays through a CompoundOptic, splitting at each surface based on reflection/transmission coefficients. Rays with flux below minFlux are discarded. ```python def traceSplit(self, rv, minFlux=1e-3, reverse=False, _verbose=False): """Recursively trace rays through this `CompoundOptic`, splitting at each surface. The return values are rays that continuing in the "forward" direction, and those reflected into the "reverse" direction. Fluxes of output rays are proportional to reflection/transmission coefficients of the interface (which may depend on wavelength and incidence angle). Note that traceSplit is applied recursively, so a single call on a `CompoundOptic` may result in many combinations of reflections/refractions being applied internally before rays are either deleted by falling below the minFlux or reach the entrace/exit of the `CompoundOptic`. Parameters ---------- rv : `batoid.RayVector` Input rays to trace minFlux : float Minimum flux value of rays to continue propagating. Default: 1e-3. reverse : bool Trace through optic in reverse? Default: False. Returns ------- forwardRays : list of batoid.RayVector. Each item in list comes from one distinct path through the optic exiting in the forward direction. The exact path traversed is accessible from the ``.path`` attribute of the item. reverseRays : list of batoid.RayVector. Each item in list comes from one distinct path through the optic exiting in the reverse direction. The exact path traversed is accessible from the ``.path`` attribute of the item. ``` -------------------------------- ### RayVector Initialization Logic Source: https://jmeyers314.github.io/batoid/_modules/batoid/rayVector.html Internal logic for initializing ray parameters, including handling optional optic properties and setting default values for back distance, stop surfaces, and media. ```python from .optic import Interface from .surface import Plane if optic is not None: if backDist is None: backDist = optic.backDist if medium is None: medium = optic.inMedium if stopSurface is None: stopSurface = optic.stopSurface if outer is None: outer = optic.pupilSize/2 if coordSys is None: coordSys = optic.coordSys if backDist is None: backDist = 40.0 if stopSurface is None: stopSurface = Interface(Plane()) if medium is None: medium = vacuum if coordSys is None: coordSys = globalCoordSys ``` -------------------------------- ### RayVector.__init__ Source: https://jmeyers314.github.io/batoid/_modules/batoid/rayVector.html Constructor for the RayVector class. Creates a RayVector from x/y coordinates on the stop surface, with options to specify the optic, back distance, medium, stop surface, wavelength, source, direction cosines, field angles, projection, and flux. ```APIDOC ## RayVector.__init__ ### Description Creates a RayVector instance with rays originating from specified coordinates on the stop surface. The rays can be traced backwards from the stop surface, and initial conditions such as medium, wavelength, and direction can be set. ### Parameters - **x** (ndarray) - Required - X coordinates on the stop surface where the rays would intersect if not refracted or reflected first. - **y** (ndarray) - Required - Y coordinates on the stop surface where the rays would intersect if not refracted or reflected first. - **optic** (batoid.Optic, optional) - Optional - If present, try to extract values for backDist, medium, and stopSurface from the Optic. Explicit keyword arguments override extracted values. - **backDist** (float, optional) - Optional - Map rays backwards from the stop surface to the plane perpendicular to the rays and backDist meters from the point (0, 0, z(0,0)) on the stop surface. If None and optic is set, infer from optic.backDist. If both None, default is 40 meters. - **medium** (batoid.Medium, optional) - Optional - Initial medium of rays. If None and optic is set, infer from optic.inMedium. If both None, default is vacuum. - **stopSurface** (batoid.Interface, optional) - Optional - Surface defining the system stop. If None and optic is set, infer from optic.stopSurface. If both None, default is Interface(Plane()). - **wavelength** (float) - Required - Vacuum wavelength of rays in meters. - **source** (None or ndarray of float, shape (3,), optional) - Optional - Where the rays originate. If None, rays originate from infinite distance and dirCos must be specified. If ndarray, rays originate from this point and dirCos is ignored. - **dirCos** (ndarray of float, shape (3,), optional) - Optional - If source is None, indicates direction of ray propagation. If source is not None, ignored. - **theta_x** (float, optional) - Optional - Field angle in radians. If source is None, indicates initial direction of propagation. If source is not None, ignored. - **theta_y** (float, optional) - Optional - Field angle in radians. If source is None, indicates initial direction of propagation. If source is not None, ignored. - **projection** (str, optional) - Optional - Projection used to convert field angle to direction cosines. Options: 'postel', 'zemax', 'gnomonic', 'stereographic', 'lambert', 'orthographic'. - **flux** (float, optional) - Optional - Flux of rays. Default is 1.0. ### Notes - If dirCos is None and source is None, dirCos is computed from theta_x, theta_y, and projection using fieldToDirCos. - If wavelength is None, a ValueError is raised. - The method uses stopSurface.surface.sag to compute z coordinates, applies a coordinate transform, and calls _finish to complete the RayVector. ``` -------------------------------- ### Copy method Source: https://jmeyers314.github.io/batoid/_modules/batoid/rayVector.html Creates a copy of the RayVector on the host. ```python def copy(self): # copy on host side for now... self._syncToHost() ret = RayVector.__new__(RayVector) ret._x = np.copy(self._x) ret._y = np.copy(self._y) ret._z = np.copy(self._z) ret._vx = np.copy(self._vx) ret._vy = np.copy(self._vy) ret._vz = np.copy(self._vz) ret._t = np.copy(self._t) ret._wavelength = np.copy(self._wavelength) ret._flux = np.copy(self._flux) ret._vignetted = np.copy(self._vignetted) ret._failed = np.copy(self._failed) ret.coordSys = self.coordSys.copy() return ret ``` -------------------------------- ### Rays.asGrid Source: https://jmeyers314.github.io/batoid/rays.html Generates a grid of rays for optical simulation. Supports regular grids and random sampling, with options to extract parameters from an Optic object. ```APIDOC ## Rays.asGrid ### Description Generates a grid of rays for optical simulation. Supports regular grids and random sampling, with options to extract parameters from an Optic object. ### Method asGrid ### Parameters - **optic** (batoid.Optic, optional) - If present, try to extract values for backDist, medium, stopSurface, and lx from the Optic. Values explicitly passed as keyword arguments override those extracted from optic. - **backDist** (float, optional) - Map rays backwards from the stop surface to the plane perpendicular to the rays and backDist meters from the point (0, 0, z(0,0)) on the stop surface. If None and optic is set, infer from optic.backDist. If both None, default 40 meters. - **medium** (batoid.Medium, optional) - Initial medium of each ray. If None and optic is set, infer from optic.inMedium. If both None, default vacuum. - **stopSurface** (batoid.Interface, optional) - Surface defining the system stop. If None and optic is set, infer from optic.stopSurface. If both None, default Interface(Plane()). - **wavelength** (float) - Vacuum wavelength of rays in meters. - **source** (None or ndarray of float, shape (3,), optional) - Where rays originate. If None, rays originate an infinite distance away, requiring dirCos. If ndarray, rays originate from this point and dirCos is ignored. - **dirCos** (ndarray of float, shape (3,), optional) - If source is None, initial direction of propagation. If source is not None, ignored. Alternative to theta_x, theta_y. - **theta_x, theta_y** (float, optional) - Field angle in radians. If source is None, initial direction of propagation. If source is not None, ignored. Uses utils.fieldToDirCos to convert to direction cosines. - **projection** ({'postel', 'zemax', 'gnomonic', 'stereographic', 'lambert', 'orthographic'}, optional) - Projection used to convert field angle to direction cosines. - **nx, ny** (int, optional) - Number of rays on each side of grid. - **dx, dy** (float or (2,) array of float, optional) - Separation in meters between adjacent rays in grid. If scalars, separations along x and y. If arrays, primitive vectors for first and second dimensions. If only dx specified, dy inferred as 90-degree rotation with same length. - **lx, ly** (float or (2,) array of float, optional) - Length of each side of ray grid. If scalars, measured along x and y. If arrays, primitive vectors orientation. If only lx specified, ly inferred as 90-degree rotation with same length. If lx is None, infer from nx and dx, then from optic.pupilSize. - **flux** (float, optional) - Flux to assign each ray. Default 1.0. - **nrandom** (None or int, optional) - If not None, uniformly sample this many rays from parallelogram region instead of regular grid. - **rng** (None or int or numpy.random.Generator, optional) - Random number generator or seed for random sampling. ### Response Returns a Rays object containing the generated grid of rays. ``` -------------------------------- ### Bicubic Class Initialization and State Management Source: https://jmeyers314.github.io/batoid/_modules/batoid/surface.html The Bicubic class constructor initializes the surface grid and computes derivatives. It also includes methods for pickling and state restoration via __getstate__ and __setstate__. ```python def __init__( self, xs, ys, zs, dzdxs=None, dzdys=None, d2zdxdys=None, nanpolicy='nan' ): assert nanpolicy.upper() in ['NAN', 'ZERO'] self._xs = np.array(xs, dtype=float, order="C") self._ys = np.array(ys, dtype=float, order="C") self._zs = np.array(zs, dtype=float, order="C") self._x0 = xs[0] self._y0 = ys[0] dx = self._dx = (self._xs[-1] - self._xs[0])/(len(self._xs)-1) dy = self._dy = (self._ys[-1] - self._ys[0])/(len(self._ys)-1) if dzdxs is None: dzdxs = np.empty_like(self._zs) dzdxs[:, 1:-1] = (self._zs[:, 2:] - self._zs[:, :-2])/(2*dx) dzdxs[:, 0] = (self._zs[:, 1] - self._zs[:, 0])/dx dzdxs[:, -1] = (self._zs[:, -1] - self._zs[:, -2])/dx if dzdys is None: dzdys = np.empty_like(self._zs) dzdys[1:-1, :] = (self._zs[2:, :] - self._zs[:-2, :])/(2*dy) dzdys[0, :] = (self._zs[1, :] - self._zs[0, :])/dy dzdys[-1, :] = (self._zs[-1, :] - self._zs[-2, :])/dy if d2zdxdys is None: d2zdxdys = np.empty_like(self._zs) d2zdxdys[:, 1:-1] = (dzdys[:, 2:] - dzdys[:, :-2])/(2*dx) d2zdxdys[:, 0] = (dzdys[:, 1] - dzdys[:, 0])/dx d2zdxdys[:, -1] = (dzdys[:, -1] - dzdys[:, -2])/dx self._dzdxs = np.array(dzdxs, dtype=float, order="C") self._dzdys = np.array(dzdys, dtype=float, order="C") self._d2zdxdys = np.array(d2zdxdys, dtype=float, order="C") self.nanpolicy = nanpolicy self._table = _batoid.CPPTable( self._x0, self._y0, self._dx, self._dy, self._zs.ctypes.data, self._dzdxs.ctypes.data, self._dzdys.ctypes.data, self._d2zdxdys.ctypes.data, len(self._xs), len(self._ys), True if self.nanpolicy.upper() == 'NAN' else False ) self._surface = _batoid.CPPBicubic(self._table) @property def xs(self): return self._xs @property def ys(self): return self._ys @property def zs(self): return self._zs @property def dzdxs(self): return self._dzdxs @property def dzdys(self): return self._dzdys @property def d2zdxdys(self): return self._d2zdxdys def __hash__(self): return hash(( "Bicubic", tuple(self.xs), tuple(self.ys), tuple(self.zs.ravel()), tuple(self.dzdxs.ravel()), tuple(self.dzdys.ravel()), tuple(self.d2zdxdys.ravel()), self.nanpolicy )) def __setstate__(self, args): (self._xs, self._ys, self._zs, self._dzdxs, self._dzdys, self._d2zdxdys, self.nanpolicy ) = args self._x0 = self._xs[0] self._y0 = self._ys[0] self._dx = (self._xs[-1] - self._xs[0])/(len(self._xs)-1) self._dy = (self._ys[-1] - self._ys[0])/(len(self._ys)-1) self._table = _batoid.CPPTable( self._x0, self._y0, self._dx, self._dy, self._zs.ctypes.data, self._dzdxs.ctypes.data, self._dzdys.ctypes.data, self._d2zdxdys.ctypes.data, len(self._xs), len(self._ys), True if self.nanpolicy.upper() == 'NAN' else False ) self._surface = _batoid.CPPBicubic(self._table) def __getstate__(self): return ( self.xs, self.ys, self.zs, self.dzdxs, self.dzdys, self.d2zdxdys, self.nanpolicy ) def __eq__(self, rhs): if not isinstance(rhs, Bicubic): return False return ( np.array_equal(self.xs, rhs.xs) and np.array_equal(self.ys, rhs.ys) and np.array_equal(self.zs, rhs.zs) and np.array_equal(self.dzdxs, rhs.dzdxs) and np.array_equal(self.dzdys, rhs.dzdys) and np.array_equal(self.d2zdxdys, rhs.d2zdxdys) and self.nanpolicy.upper() == rhs.nanpolicy.upper() ) def __repr__(self): out = f"Bicubic({self.xs!r}, {self.ys!r}, {self.zs!r}, " out += f"{self.dzdxs!r}, {self.dzdys!r}, {self.d2zdxdys!r}" if self.nanpolicy.upper() == "NAN": out += ")" else: out += ", nanpolicy='zero')" return out ``` -------------------------------- ### batoid.Coating Source: https://jmeyers314.github.io/batoid/_sources/coatings.rst.txt Documentation for the Coating class, including its members. ```APIDOC ## batoid.Coating ### Description Base class for coatings in batoid. ### Members - (Members are documented via autoclass directive; no explicit members listed in source.) ``` -------------------------------- ### Ray Vector fromStop Method Source: https://jmeyers314.github.io/batoid/_modules/batoid/rayVector.html Class method to create rays that intersect the stop surface at given points. ```python [docs] @classmethod def fromStop( cls, x, y, optic=None, backDist=None, medium=None, stopSurface=None, coordSys=None, wavelength=None, source=None, dirCos=None, theta_x=None, theta_y=None, projection='postel', flux=1 ): """Create rays that intersects the "stop" surface at given points. The algorithm used here starts by placing the rays on the "stop" surface, and then backing them up such that they are in front of any surfaces of the optic they're intended to trace. The stop surface of most large telescopes is the plane perpendicular to the optic axis and flush with the rim of the primary mirror. This plane is usually also the entrance pupil since there are no earlier refractive or reflective surfaces. However, since this plane is a bit difficult to locate automatically, the default stop surface in batoid is the global x-y plane. If a telescope has a stopSurface attribute in its yaml file, then this is usually a good choice to use in this function. Using a curved surface for the stop surface is allowed, but is usually a bad idea as this may lead to a non-uniformly illuminated pupil and is inconsistent with, say, an incoming uniform spherical wave or uniform plane wave. ``` -------------------------------- ### traceSplit(rv, minFlux=0.001, reverse=False, verbose=False) Source: https://jmeyers314.github.io/batoid/optic.html Recursively trace rays through this CompoundOptic, splitting at each surface. Returns forward and reverse rays with fluxes proportional to reflection/transmission coefficients. ```APIDOC ## traceSplit(rv, minFlux=0.001, reverse=False, verbose=False) ### Description Recursively trace rays through this CompoundOptic, splitting at each surface. Returns forward and reverse rays with fluxes proportional to reflection/transmission coefficients. ### Parameters - **rv** (batoid.RayVector) - Required - Input rays to trace - **minFlux** (float) - Optional - Minimum flux value of rays to continue propagating. Default: 1e-3. - **reverse** (bool) - Optional - Trace through optic in reverse? Default: False. - **verbose** (bool) - Optional - Verbose flag (default False). ### Returns - **forwardRays** (list of batoid.RayVector) - Each item in list comes from one distinct path through the optic exiting in the forward direction. The exact path traversed is accessible from the `.path` attribute of the item. - **reverseRays** (list of batoid.RayVector) - Each item in list comes from one distinct path through the optic exiting in the reverse direction. The exact path traversed is accessible from the `.path` attribute of the item. ### Notes Returned forward (reverse) rays will be expressed in the local coordinate system of the last (first) element of the CompoundOptic. See RayVector.toCoordSys to express rays in a different coordinate system. ```