Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
cdo
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Analyze
Contributor analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
mpim-sw
cdo
Commits
236323f1
Commit
236323f1
authored
2 years ago
by
Uwe Schulzweida
Browse files
Options
Downloads
Patches
Plain Diff
Add lib/healpix/interpolation.c
parent
ca8d0cd3
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/lib/healpix/Makefile.am
+2
-0
2 additions, 0 deletions
src/lib/healpix/Makefile.am
src/lib/healpix/interpolation.c
+222
-0
222 additions, 0 deletions
src/lib/healpix/interpolation.c
src/lib/healpix/interpolation.h
+17
-0
17 additions, 0 deletions
src/lib/healpix/interpolation.h
with
241 additions
and
0 deletions
src/lib/healpix/Makefile.am
+
2
−
0
View file @
236323f1
...
...
@@ -25,6 +25,8 @@ libhealpix_la_SOURCES = \
starutil.c
\
starutil.h
\
starutil.inc
\
interpolation.c
\
interpolation.h
\
stdint_msc.h
#
EXTRA_DIST
=
bl-nl.c
This diff is collapsed.
Click to expand it.
src/lib/healpix/interpolation.c
0 → 100644
+
222
−
0
View file @
236323f1
#include
<math.h>
#include
"interpolation.h"
#include
"healpix.h"
// Old versions of MSVC do not support C99 and therefore
// do not define NAN in math.h.
#ifndef NAN
static
const
union
{
unsigned
long
integer
;
float
value
;
}
type_punned_nan
=
{
0xFFFFFFFFFFFFFFFFul
};
#define NAN (type_punned_nan.value)
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
void
interpolate_weights
(
double
lon
,
double
lat
,
int64_t
*
ring_indices
,
double
*
weights
,
int
Nside
)
{
// Given a longitude and a latitude, Nside, and pre-allocated arrays of 4
// elements ring_indices and weights, find the ring index of the four nearest
// neighbours and the weights to use for each neighbour to interpolate.
int64_t
xy_index
,
npix
;
int64_t
ring1
,
ring2
,
ring3
,
ring4
;
double
lon1
,
lat1
,
lon2
,
lat2
;
double
lon3
,
lat3
,
lon4
,
lat4
;
double
xfrac1
,
xfrac2
,
yfrac
,
lon_frac
;
int
ring_number
,
longitude_index
,
n_in_ring
;
// Find the xy index of the pixel in which the coordinates fall
xy_index
=
radec_to_healpixl
(
lon
,
lat
,
Nside
);
// Find the lon/lat of the center of that pixel
healpixl_to_radec
(
xy_index
,
Nside
,
0
.
5
,
0
.
5
,
&
lon1
,
&
lat1
);
// Take into account possible wrapping so that the pixel longitude/latitude
// are close to the requested longitude/latitude
if
(
lon
-
lon1
>
M_PI
)
lon1
+=
2
*
M_PI
;
if
(
lon1
-
lon
>
M_PI
)
lon1
-=
2
*
M_PI
;
// Convert to a ring index and decompose into ring number and longitude index
ring1
=
healpixl_xy_to_ring
(
xy_index
,
Nside
);
if
(
ring1
<
0
)
{
int
i
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
ring_indices
[
i
]
=
-
1
;
weights
[
i
]
=
NAN
;
}
return
;
}
healpixl_decompose_ring
(
ring1
,
Nside
,
&
ring_number
,
&
longitude_index
);
// Figure out how many pixels are in the ring
if
(
ring_number
<
Nside
)
{
n_in_ring
=
4
*
ring_number
;
}
else
if
(
ring_number
<
3
*
Nside
)
{
n_in_ring
=
4
*
Nside
;
}
else
{
n_in_ring
=
(
int
)(
4
*
(
4
*
(
int64_t
)
Nside
-
(
int64_t
)
ring_number
));
}
// We now want to find the next index in the ring so that the point to
// interpolate is between the two. First we check what direction to look in by
// finding the longitude/latitude of the center of the HEALPix pixel.
if
(
lon
<
lon1
)
{
// Go to the left
if
(
longitude_index
==
0
)
{
ring2
=
ring1
+
n_in_ring
-
1
;
}
else
{
ring2
=
ring1
-
1
;
}
}
else
{
// Go to the right
if
(
longitude_index
==
n_in_ring
-
1
)
{
ring2
=
ring1
-
n_in_ring
+
1
;
}
else
{
ring2
=
ring1
+
1
;
}
}
// Find the lon/lat of the new pixel
xy_index
=
healpixl_ring_to_xy
(
ring2
,
Nside
);
healpixl_to_radec
(
xy_index
,
Nside
,
0
.
5
,
0
.
5
,
&
lon2
,
&
lat2
);
// Take into account possible wrapping so that the pixel longitude/latitude
// are close to the requested longitude/latitude
if
(
lon
-
lon2
>
M_PI
)
lon2
+=
2
*
M_PI
;
if
(
lon2
-
lon
>
M_PI
)
lon2
-=
2
*
M_PI
;
// Now check whether we are moving up or down in terms of ring index
if
(
lat
>
lat1
)
{
// Move up (0 index is at the top)
ring_number
-=
1
;
}
else
{
// Move down
ring_number
+=
1
;
}
if
(
ring_number
>
0
&&
ring_number
<
4
*
Nside
)
{
// Now figure out again how many pixels are in the ring
if
(
ring_number
<
Nside
)
{
n_in_ring
=
4
*
ring_number
;
}
else
if
(
ring_number
<
3
*
Nside
)
{
n_in_ring
=
4
*
Nside
;
}
else
{
n_in_ring
=
(
int
)(
4
*
(
4
*
(
int64_t
)
Nside
-
(
int64_t
)
ring_number
));
}
// Now determine the longitude index in which the requested longitude falls.
// In all regions, the longitude elements are spaced by 360 / n_in_ring. For
// convenience we convert the longitude index so that the spacing is 1.
lon_frac
=
lon
*
n_in_ring
/
(
2
*
M_PI
);
// In the equatorial region, the first ring starts at 0.5 and the second at
// 0 (in lon_frac space). The ring number is 1-based and the first ring in
// the equatorial region is even. In this ring we can simply take
// int(lon_frac) to get the longitude index but in the odd rings we need to
// adjust lon_frac
if
(
n_in_ring
==
4
*
Nside
&&
ring_number
%
2
==
1
)
{
// Equatorial region
lon_frac
+=
0
.
5
;
}
// Find the longitude index of the closest pixel
longitude_index
=
(
int
)
lon_frac
;
if
(
longitude_index
==
n_in_ring
)
{
longitude_index
-=
1
;
}
// Find the longitude/latitude and ring index of this pixel
ring3
=
healpixl_compose_ring
(
ring_number
,
longitude_index
,
Nside
);
xy_index
=
healpixl_ring_to_xy
(
ring3
,
Nside
);
healpixl_to_radec
(
xy_index
,
Nside
,
0
.
5
,
0
.
5
,
&
lon3
,
&
lat3
);
// Take into account possible wrapping so that the pixel longitude/latitude
// are close to the requested longitude/latitude
if
(
lon
-
lon3
>
M_PI
)
lon3
+=
2
*
M_PI
;
if
(
lon3
-
lon
>
M_PI
)
lon3
-=
2
*
M_PI
;
// Finally we can find the fourth pixel as before
if
(
lon
<
lon3
)
{
// Go to the left
if
(
longitude_index
==
0
)
{
ring4
=
ring3
+
n_in_ring
-
1
;
}
else
{
ring4
=
ring3
-
1
;
}
}
else
{
// Go to the right
if
(
longitude_index
==
n_in_ring
-
1
)
{
ring4
=
ring3
-
n_in_ring
+
1
;
}
else
{
ring4
=
ring3
+
1
;
}
}
xy_index
=
healpixl_ring_to_xy
(
ring4
,
Nside
);
healpixl_to_radec
(
xy_index
,
Nside
,
0
.
5
,
0
.
5
,
&
lon4
,
&
lat4
);
// Take into account possible wrapping so that the pixel longitude/latitude
// are close to the requested longitude/latitude
if
(
lon
-
lon4
>
M_PI
)
lon4
+=
2
*
M_PI
;
if
(
lon4
-
lon
>
M_PI
)
lon4
-=
2
*
M_PI
;
// Determine the interpolation weights
xfrac1
=
(
lon
-
lon1
)
/
(
lon2
-
lon1
);
xfrac2
=
(
lon
-
lon3
)
/
(
lon4
-
lon3
);
yfrac
=
(
lat
-
lat1
)
/
(
lat3
-
lat1
);
weights
[
0
]
=
(
1
-
xfrac1
)
*
(
1
-
yfrac
);
weights
[
1
]
=
xfrac1
*
(
1
-
yfrac
);
weights
[
2
]
=
(
1
-
xfrac2
)
*
yfrac
;
weights
[
3
]
=
xfrac2
*
yfrac
;
}
else
{
// In the case where we are inside the four top/bottom-most
// values, we effectively place a value at the pole that
// is the average of the four values, and the interpolation
// is the weighted average of this polar value and the
// value interpolated along the ring.
xfrac1
=
(
lon
-
lon1
)
/
(
lon2
-
lon1
);
yfrac
=
(
lat
-
lat1
)
/
(
0
.
5
*
M_PI
-
lat1
);
if
(
ring_number
==
0
)
{
ring3
=
(
ring1
+
2
)
%
4
;
ring4
=
(
ring2
+
2
)
%
4
;
yfrac
=
(
lat
-
lat1
)
/
(
0
.
5
*
M_PI
-
lat1
);
}
else
{
npix
=
12
*
(
int64_t
)
Nside
*
(
int64_t
)
Nside
;
ring3
=
((
ring1
-
(
npix
-
4
))
+
2
)
%
4
+
npix
-
4
;
ring4
=
((
ring2
-
(
npix
-
4
))
+
2
)
%
4
+
npix
-
4
;
yfrac
=
(
lat
-
lat1
)
/
(
-
0
.
5
*
M_PI
-
lat1
);
}
weights
[
0
]
=
(
1
-
xfrac1
)
*
(
1
-
yfrac
)
+
0
.
25
*
yfrac
;
weights
[
1
]
=
xfrac1
*
(
1
-
yfrac
)
+
0
.
25
*
yfrac
;
weights
[
2
]
=
0
.
25
*
yfrac
;
weights
[
3
]
=
0
.
25
*
yfrac
;
}
ring_indices
[
0
]
=
ring1
;
ring_indices
[
1
]
=
ring2
;
ring_indices
[
2
]
=
ring3
;
ring_indices
[
3
]
=
ring4
;
}
This diff is collapsed.
Click to expand it.
src/lib/healpix/interpolation.h
0 → 100644
+
17
−
0
View file @
236323f1
#ifndef ASTROPY_HEALPIX_INTERPOLATION_INCL
#define ASTROPY_HEALPIX_INTERPOLATION_INCL
#ifdef _MSC_VER
#if _MSC_VER >= 1600
#include
<stdint.h>
#else
#include
<stdint_msc.h>
#endif
#else
#include
<stdint.h>
#endif
void
interpolate_weights
(
double
lon
,
double
lat
,
int64_t
*
ring_indices
,
double
*
weights
,
int
Nside
);
#endif
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment