Skip to content

Commit 6750df4

Browse files
Merge pull request #395 from observerly/feature/optics/getFieldOfView
feat: add getFieldOfView() to optics module in @observerly/astrometry
2 parents 55baa30 + 4ed970d commit 6750df4

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

src/optics.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
/*****************************************************************************************************************/
88

9+
import { type CartesianCoordinate } from './common'
10+
11+
import { convertRadiansToDegrees as degrees } from './utilities'
12+
13+
/*****************************************************************************************************************/
14+
915
type FocalRatio = `f/${number}`
1016

1117
/*****************************************************************************************************************/
@@ -32,3 +38,45 @@ export function getFocalRatio(apertureWidth: number, focalLength: number): Focal
3238
}
3339

3440
/*****************************************************************************************************************/
41+
42+
/**
43+
*
44+
* getFieldOfView()
45+
*
46+
* @param focalLength - the focal length of the optics (in meters)
47+
* @param pixelSize - the pixel size of the camera (in meters)
48+
* @param resolution - the resolution of the camera (in pixels)
49+
* @param binning - the binning of the camera (in pixels)
50+
* @returns the field of view (FOV) of the camera (in degrees)
51+
*/
52+
export function getFieldOfView(
53+
focalLength: number,
54+
pixelSize: number,
55+
resolution: Omit<CartesianCoordinate, 'z'>
56+
): Omit<CartesianCoordinate, 'z'> {
57+
// Check that the focal length is a sensible number, e.g., > 0:
58+
if (focalLength < 0) {
59+
throw new Error(`Invalid focal ratio as focal length is negative`)
60+
}
61+
62+
// Check that the pixel size is a sensible number, e.g., > 0:
63+
if (pixelSize < 0) {
64+
throw new Error(`Invalid focal ratio as pixel size is negative`)
65+
}
66+
67+
// Check that the resolution is a sensible number, e.g., > 0:
68+
if (resolution.x < 0 || resolution.y < 0) {
69+
throw new Error(`Invalid focal ratio as resolution is negative`)
70+
}
71+
72+
// Get the angular size of a pixel of the camera (in degrees):
73+
const θ = degrees(pixelSize / focalLength)
74+
75+
// Return the field of view (FOV)
76+
return {
77+
x: resolution.x * θ,
78+
y: resolution.y * θ
79+
}
80+
}
81+
82+
/*****************************************************************************************************************/

tests/optics.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*****************************************************************************************************************/
2+
3+
// @author Michael Roberts <[email protected]>
4+
// @package @observerly/astrometry/observer
5+
// @license Copyright © 2021-2024 observerly
6+
7+
/*****************************************************************************************************************/
8+
9+
import { describe, expect, it } from 'vitest'
10+
11+
import { getFieldOfView } from '../src'
12+
13+
/*****************************************************************************************************************/
14+
15+
// For testing we will fix the aperture to be 0.08m (80mm):
16+
export const apertureWidth = 0.08
17+
18+
// For testing we will fix the focal length to be 0.6m (600mm):
19+
export const focalLength = 0.6
20+
21+
// For testing we will fix the pixel size to be 6.45μm:
22+
export const pixelSize = 6.45e-6
23+
24+
/*****************************************************************************************************************/
25+
26+
describe('getFieldOfView', () => {
27+
it('should be defined', () => {
28+
expect(getFieldOfView).toBeDefined
29+
})
30+
31+
it('should return the correct value for a 600mm focal length', () => {
32+
const fov = getFieldOfView(focalLength, pixelSize, { x: 1392, y: 1040 })
33+
// 0.86° x 0.64° field of view:
34+
expect(fov.x).toBe(0.857374044633764)
35+
expect(fov.y).toBe(0.6405668149562604)
36+
})
37+
38+
it('should return the correct value for a 1000mm focal length', () => {
39+
const fov = getFieldOfView(1.0, pixelSize, { x: 1392, y: 1040 })
40+
// 0.51° x 0.38° field of view:
41+
expect(fov.x).toBe(0.5144244267802583)
42+
expect(fov.y).toBe(0.3843400889737562)
43+
})
44+
45+
it('should return the correct value for a 600mm focal length and a 8.25μm pixel size', () => {
46+
const fov = getFieldOfView(focalLength, 8.25e-6, { x: 1392, y: 1040 })
47+
// 1.1° x 0.82° field of view:
48+
expect(fov.x).toBe(1.0966412198803959)
49+
expect(fov.y).toBe(0.8193296470370773)
50+
})
51+
})
52+
53+
/*****************************************************************************************************************/

0 commit comments

Comments
 (0)