Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1a782ae

Browse files
authored
Merge pull request#8 from msdemlei/add-proper-motions
Add code for epoch propagation
2 parentsef881cd +7c3e5a4 commit1a782ae

File tree

9 files changed

+605
-7
lines changed

9 files changed

+605
-7
lines changed

‎Makefile‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ MODULE_big = pg_sphere
77
OBJS = sscan.o sparse.o sbuffer.o vector3d.o point.o\
88
euler.o circle.o line.o ellipse.o polygon.o\
99
path.o box.o output.o gq_cache.o gist.o key.o\
10-
gnomo.o healpix.o moc.o process_moc.o healpix_bare/healpix_bare.o
10+
gnomo.o healpix.o moc.o process_moc.o healpix_bare/healpix_bare.o\
11+
epochprop.o
1112

1213
EXTENSION = pg_sphere
1314
RELEASE_SQL =$(EXTENSION)--$(PGSPHERE_VERSION).sql
@@ -23,13 +24,13 @@ DATA_built = $(RELEASE_SQL) \
2324
DOCS = README.pg_sphere COPYRIGHT.pg_sphere
2425
REGRESS = init tables points euler circle line ellipse poly path box index\
2526
contains_ops contains_ops_compat bounding_box_gist gnomo healpix\
26-
moc mocautocast
27+
moc mocautocast epochprop
2728

2829
REGRESS_9_5 = index_9.5# experimental for spoint3
2930

3031
TESTS = init_test tables points euler circle line ellipse poly path box index\
3132
contains_ops contains_ops_compat bounding_box_gist gnomo healpix\
32-
moc mocautocast
33+
moc mocautocast epochprop
3334

3435
ifndefCXXFLAGS
3536
# no support for CXXFLAGS in PGXS before v11
@@ -39,15 +40,15 @@ endif
3940

4041
EXTRA_CLEAN =$(PGS_SQL) pg_sphere.test.sql
4142

42-
CRUSH_TESTS = init_extended circle_extended
43+
CRUSH_TESTS = init_extended circle_extended
4344

4445
# order of sql files is important
4546
PGS_SQL = pgs_types.sql pgs_point.sql pgs_euler.sql pgs_circle.sql\
4647
pgs_line.sql pgs_ellipse.sql pgs_polygon.sql pgs_path.sql\
4748
pgs_box.sql pgs_contains_ops.sql pgs_contains_ops_compat.sql\
4849
pgs_gist.sql gnomo.sql\
4950
healpix.sql pgs_gist_spoint3.sql pgs_moc_type.sql pgs_moc_compat.sql pgs_moc_ops.sql\
50-
pgs_moc_geo_casts.sql
51+
pgs_moc_geo_casts.sql pgs_epochprop.sql
5152
PGS_SQL_9_5 = pgs_9.5.sql# experimental for spoint3
5253

5354
USE_PGXS = 1
@@ -199,7 +200,7 @@ ifeq ($(has_parallel), n)
199200
sed -i -e '/PARALLEL/d' $@# version $(pg_version) does not have support for PARALLEL
200201
endif
201202

202-
pg_sphere--1.2.0--1.2.1.sql: pgs_moc_geo_casts.sql.in
203+
pg_sphere--1.2.0--1.2.1.sql: pgs_moc_geo_casts.sql.in pgs_epochprop.sql.in
203204
cat$^>$@
204205
ifeq ($(has_parallel), n)
205206
sed -i -e '/PARALLEL/d' $@# version $(pg_version) does not have support for PARALLEL

‎doc/functions.sgm‎

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,5 +667,133 @@
667667
</example>
668668

669669
</sect2>
670-
670+
671+
<sect2 id="funcs.epochprop">
672+
<title>
673+
Epoch propagation
674+
</title>
675+
676+
<sect3 id="funcs.epochprop.full">
677+
<title>6-Parameter Epoch Propagation</title>
678+
<funcsynopsis>
679+
<funcprototype>
680+
<funcdef><type>double precision[6]</type>
681+
<function>epoch_prop</function></funcdef>
682+
<paramdef>spoint <parameter>pos</parameter></paramdef>
683+
<paramdef>double precision <parameter>parallax</parameter></paramdef>
684+
<paramdef>double precision <parameter>pm_long</parameter></paramdef>
685+
<paramdef>double precision <parameter>pm_lat</parameter></paramdef>
686+
<paramdef>double precision <parameter>radial_velocity</parameter></paramdef>
687+
<paramdef>double precision <parameter>delta_t</parameter></paramdef>
688+
</funcprototype>
689+
</funcsynopsis>
690+
<para>
691+
Propagates a spherical phase vector in time (in particular,
692+
applies proper motion to positions)
693+
</para>
694+
<para>
695+
Following both pg_sphere and, where missing, astronomical
696+
conventions makes units somewhat eclectic here; pm_long and pm_lat
697+
need to be in rad/yr, whereas parallax is in mas, and
698+
radial_velocity in km/s. The time difference must be in
699+
(Julian) years.
700+
</para>
701+
702+
<para>
703+
This function returns a 6-array of [long, lat, parallax,
704+
pm_long, pm_lat, radial_velocity] of the corresponding values
705+
delta_t years after the reference epoch for the original position.
706+
As in the function arguments, long and lat are in rad, pm_lon and
707+
pm_lat are in rad/yr, parallax is in mas, and radial_velocity is
708+
in km/s. If you are only interested in the position, consider
709+
the epoch_prop_pos functions below that have a somewhat less
710+
contorted signature.
711+
</para>
712+
713+
<para>
714+
It is an error to have either pos or delta_t NULL. For all
715+
other arguments, NULLs are turned into 0s, except for parallax,
716+
where some very small default is put in. In that case,
717+
both parallax and radial_velocity will be NULL in the output
718+
array.
719+
</para>
720+
721+
<para>
722+
This uses the rigorous method derived in "The Hipparcos and Tycho
723+
Catalogues", ESA Special Publication 1200 (1997), p 94f. It does
724+
not take into account relativistic effects, and it also does not
725+
account for secular aberration.
726+
</para>
727+
<example>
728+
<title>Propagating Barnard's star into the past</title>
729+
<programlisting><![CDATA[
730+
SELECT
731+
to_char(DEGREES(tp[1]), '999D9999999999'),
732+
to_char(DEGREES(tp[2]), '999D9999999999'),
733+
to_char(tp[3], '999D999'),
734+
to_char(DEGREES(tp[4])*3.6e6, '999D999'),
735+
to_char(DEGREES(tp[5])*3.6e6, '99999D999'),
736+
to_char(tp[6], '999D999')
737+
FROM (
738+
SELECT epoch_prop(
739+
spoint(radians(269.45207695), radians(4.693364966)), 546.9759,
740+
RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6), -110,
741+
-100) AS tp) AS q;
742+
to_char | to_char | to_char | to_char | to_char | to_char
743+
-----------------+-----------------+----------+----------+------------+----------
744+
269.4742714391 | 4.4072939987 | 543.624 | -791.442 | 10235.412 | -110.450
745+
]]></programlisting>
746+
</example>
747+
748+
</sect3>
749+
<sect3>
750+
<title>Epoch Propagation of Positions Only</title>
751+
<funcsynopsis>
752+
<funcprototype>
753+
<funcdef><type>spoint</type>
754+
<function>epoch_prop_pos</function></funcdef>
755+
<paramdef>spoint <parameter>pos</parameter></paramdef>
756+
<paramdef>double precision <parameter>parallax</parameter></paramdef>
757+
<paramdef>double precision <parameter>pm_long</parameter></paramdef>
758+
<paramdef>double precision <parameter>pm_lat</parameter></paramdef>
759+
<paramdef>double precision <parameter>radial_velocity</parameter></paramdef>
760+
<paramdef>double precision <parameter>delta_t</parameter></paramdef>
761+
</funcprototype>
762+
</funcsynopsis>
763+
<funcsynopsis>
764+
<funcprototype>
765+
<funcdef><type>spoint</type>
766+
<function>epoch_prop_pos</function></funcdef>
767+
<paramdef>spoint <parameter>pos</parameter></paramdef>
768+
<paramdef>double precision <parameter>pm_long</parameter></paramdef>
769+
<paramdef>double precision <parameter>pm_lat</parameter></paramdef>
770+
<paramdef>double precision <parameter>delta_t</parameter></paramdef>
771+
</funcprototype>
772+
</funcsynopsis>
773+
<para>
774+
These are simplified versions of epoch_prop returning only spoints;
775+
the propagated values for the other coordinates are discarded
776+
(but still internallay computed; these functions do not
777+
run any faster than epoch_prop itself).
778+
</para>
779+
780+
<para>
781+
As with epoch_prop itself, missing values (except for pos and
782+
delta_t) are substituted by 0 (or a very small value in the
783+
case of parallax).
784+
</para>
785+
<example>
786+
<title>Barnard's star, position and proper motion</title>
787+
<programlisting><![CDATA[
788+
SELECT epoch_prop_pos(
789+
spoint(radians(269.45207695), radians(4.693364966)),
790+
RADIANS(-801.551/3.6e6), RADIANS(10362/3.6e6),
791+
20) AS tp;
792+
tp
793+
-----------------------------------------
794+
(4.70274793061952 , 0.0829193989380876)
795+
]]></programlisting>
796+
</example>
797+
</sect3>
798+
</sect2>
671799
</sect1>

‎epochprop.c‎

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/* Handling of (conventional) proper motions.
2+
3+
This code is largely based on a FORTRAN function written by Lennart Lindegren
4+
(Lund Obs) in 1995 that implements the procedure described in The Hipparcos
5+
and Tycho Catalogues (ESA SP-1200), Volume 1, Section 1.5.5, 'Epoch
6+
Transformation: Rigorous Treatment'; cf.
7+
<https://www.cosmos.esa.int/documents/532822/552851/vol1_all.pdf/99adf6e3-6893-4824-8fc2-8d3c9cbba2b5>.
8+
*/
9+
10+
#include<math.h>
11+
#include<pgs_util.h>
12+
13+
#include"point.h"
14+
#include"epochprop.h"
15+
#include"vector3d.h"
16+
17+
PG_FUNCTION_INFO_V1(epoch_prop);
18+
19+
/* Astronomical unit in kilometers */
20+
#defineAU 1.495978701e8
21+
22+
/* Julian year in seconds */
23+
#defineJ_YEAR (365.25*86400)
24+
25+
/* A_nu as per ESA/SP-1200 */
26+
#defineA_NU (AU/(J_YEAR))
27+
28+
/* Following SOFA, we use 1e-7 arcsec as minimal parallax
29+
("celestial sphere"); parallax=0 exactly means "infinite distance", which
30+
leads to all sorts for problems; our parallaxes come in in mas, so: */
31+
#definePX_MIN 1e-7*1000
32+
33+
/* propagate an object at a phase vector over a time difference of delta_t,
34+
stuffing an updated phase vector in result.
35+
36+
This does not propagate errors.
37+
*/
38+
staticvoidpropagate_phasevec(
39+
constphasevec*pv,
40+
constdoubledelta_t,
41+
phasevec*result) {
42+
43+
doubledistance_factor,mu0abs,zeta0,parallax;
44+
45+
Vector3Dp0,r0,q0;
46+
Vector3Dmu0,pprime,qprime,mu,muprime,u,uprime;
47+
48+
/* for very small or null parallaxes, our algorithm breaks; avoid that
49+
and, if we did emergency measures, do not talk about parallax and
50+
radial velocity in the output */
51+
if (pv->parallax_valid) {
52+
parallax=pv->parallax;
53+
}else {
54+
parallax=PX_MIN;
55+
}
56+
result->parallax_valid=pv->parallax_valid;
57+
58+
/* compute the normal triad as Vector3D-s, eq. (1.2.15)*/
59+
spoint_vector3d(&r0,&(pv->pos));
60+
61+
p0.x=-sin(pv->pos.lng);
62+
p0.y=cos(pv->pos.lng);
63+
p0.z=0;
64+
65+
q0.x=-sin(pv->pos.lat)*cos(pv->pos.lng);
66+
q0.y=-sin(pv->pos.lat)*sin(pv->pos.lng);
67+
q0.z=cos(pv->pos.lat);
68+
69+
/* the original proper motion vector */
70+
mu0.x=mu0.y=mu0.z=0;
71+
vector3d_addwithscalar(&mu0,pv->pm[0],&p0);
72+
vector3d_addwithscalar(&mu0,pv->pm[1],&q0);
73+
mu0abs=vector3d_length(&mu0);
74+
75+
/* radial velocity in mas/yr ("change of parallax per year"). eq. (1.5.24)
76+
We're transforming this to rad/yr so the units work out below */
77+
zeta0= (pv->rv*parallax /A_NU) /3.6e6 /RADIANS;
78+
/* distance factor eq. (1.5.25) */
79+
distance_factor=1/sqrt(1
80+
+2*zeta0*delta_t
81+
+ (mu0abs*mu0abs+zeta0*zeta0)*delta_t*delta_t);
82+
83+
/* the propagated proper motion vector, eq. (1.5.28) */
84+
muprime.x=muprime.y=muprime.z=0;
85+
vector3d_addwithscalar(&muprime, (1+zeta0*delta_t),&mu0);
86+
vector3d_addwithscalar(&muprime,-mu0abs*mu0abs*delta_t,&r0);
87+
mu.x=mu.y=mu.z=0;
88+
vector3d_addwithscalar(&mu,pow(distance_factor,3),&muprime);
89+
90+
/* parallax, eq. (1.5.27) */
91+
result->parallax=distance_factor*parallax;
92+
/* zeta/rv, eq. (1.5.29); go back from rad to mas, too */
93+
result->rv= (zeta0+ (mu0abs*mu0abs+zeta0*zeta0)*delta_t)
94+
*distance_factor*distance_factor
95+
*3.6e6*RADIANS
96+
*A_NU /result->parallax;
97+
98+
/* propagated position, eq. (1.5.26) */
99+
uprime.x=uprime.y=uprime.z=0;
100+
vector3d_addwithscalar(&uprime, (1+zeta0*delta_t),&r0);
101+
vector3d_addwithscalar(&uprime,delta_t,&mu0);
102+
u.x=u.y=u.z=0;
103+
vector3d_addwithscalar(&u,distance_factor,&uprime);
104+
vector3d_spoint(&(result->pos),&u);
105+
106+
/* compute a new triad for the propagated position, eq (1.5.15) */
107+
pprime.x=-sin(result->pos.lng);
108+
pprime.y=cos(result->pos.lng);
109+
pprime.z=0;
110+
qprime.x=-sin(result->pos.lat)*cos(result->pos.lng);
111+
qprime.y=-sin(result->pos.lat)*sin(result->pos.lng);
112+
qprime.z=cos(result->pos.lat);
113+
114+
/* use it to compute the proper motions, eq. (1.5.32) */
115+
result->pm[0]=vector3d_scalar(&pprime,&mu);
116+
result->pm[1]=vector3d_scalar(&qprime,&mu);
117+
}
118+
119+
120+
/*
121+
Propagate a position with proper motions and optionally parallax
122+
and radial velocity.
123+
124+
Arguments: pos0 (spoint), pm_long, pm_lat (in rad/yr)
125+
par (parallax, mas), rv (in km/s), delta_t (in years)
126+
127+
This returns a 6-array of lat, long (in rad), parallax (in mas)
128+
pmlat, pmlong (in rad/yr), rv (in km/s).
129+
*/
130+
Datum
131+
epoch_prop(PG_FUNCTION_ARGS) {
132+
doubledelta_t;
133+
phasevecinput,output;
134+
ArrayType*result;
135+
Datumretvals[6];
136+
137+
if (PG_ARGISNULL(0)) {
138+
ereport(ERROR,
139+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
140+
errmsg("NULL position not supported in epoch propagation"))); }
141+
memcpy(&(input.pos), (void*)PG_GETARG_POINTER(0),sizeof(SPoint));
142+
if (PG_ARGISNULL(1)) {
143+
input.parallax=0;
144+
}else {
145+
input.parallax=PG_GETARG_FLOAT8(1);
146+
}
147+
input.parallax_valid=fabs(input.parallax)>PX_MIN;
148+
149+
if (PG_ARGISNULL(2)) {
150+
input.pm[0]=0;
151+
}else {
152+
input.pm[0]=PG_GETARG_FLOAT8(2);
153+
}
154+
155+
if (PG_ARGISNULL(3)) {
156+
input.pm[1]=0;
157+
}else {
158+
input.pm[1]=PG_GETARG_FLOAT8(3);
159+
}
160+
161+
if (PG_ARGISNULL(4)) {
162+
input.rv=0;
163+
}else {
164+
input.rv=PG_GETARG_FLOAT8(4);
165+
}
166+
167+
if (PG_ARGISNULL(5)) {
168+
ereport(ERROR,
169+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
170+
errmsg("NULL delta t not supported in epoch propagation"))); }
171+
delta_t=PG_GETARG_FLOAT8(5);
172+
173+
propagate_phasevec(&input,delta_t,&output);
174+
175+
/* change to internal units: rad, rad/yr, mas, and km/s */
176+
retvals[0]=Float8GetDatum(output.pos.lng);
177+
retvals[1]=Float8GetDatum(output.pos.lat);
178+
retvals[2]=Float8GetDatum(output.parallax);
179+
retvals[3]=Float8GetDatum(output.pm[0]);
180+
retvals[4]=Float8GetDatum(output.pm[1]);
181+
retvals[5]=Float8GetDatum(output.rv);
182+
183+
{
184+
boolisnull[6]= {0,0,0,0,0,0};
185+
intlower_bounds[1]= {1};
186+
intdims[1]= {6};
187+
#ifdefUSE_FLOAT8_BYVAL
188+
boolembyval= true;
189+
#else
190+
boolembyval= false;
191+
#endif
192+
193+
if (!output.parallax_valid) {
194+
/* invalidate parallax and rv */
195+
isnull[2]=1;
196+
isnull[5]=1;
197+
}
198+
199+
result=construct_md_array(retvals,isnull,1,dims,lower_bounds,
200+
FLOAT8OID,sizeof(float8),embyval,'d');
201+
}
202+
PG_RETURN_ARRAYTYPE_P(result);
203+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp