Coverage Report

Created: 2026-09-14 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/sofars-0.6.1/src/astro/pvstar.rs
Line
Count
Source
1
use crate::{
2
    consts::{DAU, DAYSEC, DC, DJY, DR2AS},
3
    vm::{anp, pdp, pm, pmp, pn, ppp, pv2s, sxp},
4
};
5
6
///  Space motion pv−vector to star catalog data
7
///
8
///  Convert star position+velocity vector to catalog coordinates.
9
///
10
///  This function is part of the International Astronomical Union's
11
///  SOFA (Standards of Fundamental Astronomy) software collection.
12
///
13
///  Status:  support function.
14
///
15
///  Given (Note 1):
16
///  ```
17
///     pv     double[2][3]   pv-vector (au, au/day)
18
///  ```
19
///  Returned (Note 2):
20
///  ```
21
///     ra     double         right ascension (radians)
22
///     dec    double         declination (radians)
23
///     pmr    double         RA proper motion (radians/year)
24
///     pmd    double         Dec proper motion (radians/year)
25
///     px     double         parallax (arcsec)
26
///     rv     double         radial velocity (km/s, positive = receding)
27
///  ```
28
///  Returned (function value):
29
///  ```
30
///            int            status:
31
///                              0 = OK
32
///                             -1 = superluminal speed (Note 5)
33
///                             -2 = null position vector
34
///  ```
35
///  Notes:
36
///
37
///  1) The specified pv-vector is the coordinate direction (and its rate
38
///     of change) for the date at which the light leaving the star
39
///     reached the solar-system barycenter.
40
///
41
///  2) The star data returned by this function are "observables" for an
42
///     imaginary observer at the solar-system barycenter.  Proper motion
43
///     and radial velocity are, strictly, in terms of barycentric
44
///     coordinate time, TCB.  For most practical applications, it is
45
///     permissible to neglect the distinction between TCB and ordinary
46
///     "proper" time on Earth (TT/TAI).  The result will, as a rule, be
47
///     limited by the intrinsic accuracy of the proper-motion and
48
///     radial-velocity data;  moreover, the supplied pv-vector is likely
49
///     to be merely an intermediate result (for example generated by the
50
///     function iauStarpv), so that a change of time unit will cancel
51
///     out overall.
52
///
53
///     In accordance with normal star-catalog conventions, the object's
54
///     right ascension and declination are freed from the effects of
55
///     secular aberration.  The frame, which is aligned to the catalog
56
///     equator and equinox, is Lorentzian and centered on the SSB.
57
///
58
///     Summarizing, the specified pv-vector is for most stars almost
59
///     identical to the result of applying the standard geometrical
60
///     "space motion" transformation to the catalog data.  The
61
///     differences, which are the subject of the Stumpff paper cited
62
///     below, are:
63
///
64
///     (i) In stars with significant radial velocity and proper motion,
65
///     the constantly changing light-time distorts the apparent proper
66
///     motion.  Note that this is a classical, not a relativistic,
67
///     effect.
68
///
69
///     (ii) The transformation complies with special relativity.
70
///
71
///  3) Care is needed with units.  The star coordinates are in radians
72
///     and the proper motions in radians per Julian year, but the
73
///     parallax is in arcseconds; the radial velocity is in km/s, but
74
///     the pv-vector result is in au and au/day.
75
///
76
///  4) The proper motions are the rate of change of the right ascension
77
///     and declination at the catalog epoch and are in radians per Julian
78
///     year.  The RA proper motion is in terms of coordinate angle, not
79
///     true angle, and will thus be numerically larger at high
80
///     declinations.
81
///
82
///  5) Straight-line motion at constant speed in the inertial frame is
83
///     assumed.  If the speed is greater than or equal to the speed of
84
///     light, the function aborts with an error status.
85
///
86
///  6) The inverse transformation is performed by the function iauStarpv.
87
///
88
///  Called:
89
///  ```
90
///     iauPn        decompose p-vector into modulus and direction
91
///     iauPdp       scalar product of two p-vectors
92
///     iauSxp       multiply p-vector by scalar
93
///     iauPmp       p-vector minus p-vector
94
///     iauPm        modulus of p-vector
95
///     iauPpp       p-vector plus p-vector
96
///     iauPv2s      pv-vector to spherical
97
///     iauAnp       normalize angle into range 0 to 2pi
98
///  ```
99
///  Reference:
100
///
101
///     Stumpff, P., 1985, Astron.Astrophys. 144, 232-240.
102
0
pub fn pvstar(pv: &[[f64; 3]; 2]) -> Result<[f64; 6], i32> {
103
0
    let mut pv = *pv;
104
    let d: f64;
105
    let w: f64;
106
    let del: f64;
107
108
    // Isolate the radial component of the velocity (au/day, inertial).
109
0
    let (_, pu) = pn(&pv[0]);
110
0
    let vr = pdp(&pu, &pv[1]);
111
0
    let ur = sxp(vr, &pu);
112
113
    // Isolate the transverse component of the velocity (au/day, inertial).
114
0
    let ut = pmp(&pv[1], &ur);
115
0
    let vt = pm(ut);
116
117
    // Special-relativity dimensionless parameters.
118
0
    let bett = vt / DC;
119
0
    let betr = vr / DC;
120
121
    // The observed-to-inertial correction terms.
122
0
    d = 1.0 + betr;
123
0
    w = betr * betr + bett * bett;
124
0
    if d == 0.0 || w > 1.0 {
125
0
        return Err(-1);
126
0
    }
127
0
    del = -w / ((1.0 - w).sqrt() + 1.0);
128
129
    // Scale inertial tangential velocity vector into observed (au/d).
130
0
    let ust = sxp(1.0 / d, &ut);
131
132
    // Compute observed radial velocity vector (au/d).
133
0
    let usr = sxp(DC * (betr - del) / d, &pu);
134
135
    // Combine the two to obtain the observed velocity vector.
136
0
    pv[1] = ppp(&usr, &ust);
137
138
    // Cartesian to spherical.
139
0
    let (mut ra, dec, r, rad, decd, rd) = pv2s(&pv);
140
0
    if r == 0.0 {
141
0
        return Err(-2);
142
0
    }
143
144
    // Return RA in range 0 to 2pi.
145
0
    ra = anp(ra);
146
147
    // Return proper motions in radians per year.
148
0
    let pmr = rad * DJY;
149
0
    let pmd = decd * DJY;
150
151
    // Return parallax in arcsec.
152
0
    let px = DR2AS / r;
153
154
    // Return radial velocity in km/s.
155
0
    let rv = 1e-3 * rd * DAU / DAYSEC;
156
157
    // Success.
158
0
    Ok([ra, dec, pmr, pmd, px, rv])
159
0
}