/usr/lib/python3/dist-packages/reproject/spherical_intersect/core.py is in python3-reproject 0.3.1-4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | # Licensed under a 3-clause BSD style license - see LICENSE.rst
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import signal
import numpy as np
from ..wcs_utils import convert_world_coordinates
from ._overlap import _compute_overlap
def _init_worker():
"""
Function to disable ctrl+c in the worker processes.
"""
signal.signal(signal.SIGINT, signal.SIG_IGN)
def _reproject_slice(args):
from ._overlap import _reproject_slice_cython
return _reproject_slice_cython(*args)
def _reproject_celestial(array, wcs_in, wcs_out, shape_out, parallel=True, _legacy=False):
# Check the parallel flag.
if type(parallel) != bool and type(parallel) != int:
raise TypeError("The 'parallel' flag must be a boolean or integral value")
if type(parallel) == int:
# parallel is a number of processes.
if parallel <= 0:
raise ValueError("The number of processors to use must be strictly positive")
nproc = parallel
else:
# parallel is a boolean flag. nproc = None here means automatically selected
# number of processes.
nproc = None if parallel else 1
# Convert input array to float values. If this comes from a FITS, it might have
# float32 as value type and that can break things in Cython
array = np.asarray(array, dtype=float)
# TODO: make this work for n-dimensional arrays
if wcs_in.naxis != 2:
raise NotImplementedError("Only 2-dimensional arrays can be reprojected at this time")
# TODO: at the moment, we compute the coordinates of all of the corners,
# but we might want to do it in steps for large images.
# Start off by finding the world position of all the corners of the input
# image in world coordinates
ny_in, nx_in = array.shape
x = np.arange(nx_in + 1.) - 0.5
y = np.arange(ny_in + 1.) - 0.5
xp_in, yp_in = np.meshgrid(x, y)
xw_in, yw_in = wcs_in.wcs_pix2world(xp_in, yp_in, 0)
# Now compute the world positions of all the corners in the output header
ny_out, nx_out = shape_out
x = np.arange(nx_out + 1.) - 0.5
y = np.arange(ny_out + 1.) - 0.5
xp_out, yp_out = np.meshgrid(x, y)
xw_out, yw_out = wcs_out.wcs_pix2world(xp_out, yp_out, 0)
# Convert the input world coordinates to the frame of the output world
# coordinates.
xw_in, yw_in = convert_world_coordinates(xw_in, yw_in, wcs_in, wcs_out)
# Finally, compute the pixel positions in the *output* image of the pixels
# from the *input* image.
xp_inout, yp_inout = wcs_out.wcs_world2pix(xw_in, yw_in, 0)
if _legacy:
# Create output image
array_new = np.zeros(shape_out)
weights = np.zeros(shape_out)
for i in range(nx_in):
for j in range(ny_in):
# For every input pixel we find the position in the output image in
# pixel coordinates, then use the full range of overlapping output
# pixels with the exact overlap function.
xmin = int(min(xp_inout[j, i], xp_inout[j, i + 1], xp_inout[j + 1, i + 1], xp_inout[j + 1, i]) + 0.5)
xmax = int(max(xp_inout[j, i], xp_inout[j, i + 1], xp_inout[j + 1, i + 1], xp_inout[j + 1, i]) + 0.5)
ymin = int(min(yp_inout[j, i], yp_inout[j, i + 1], yp_inout[j + 1, i + 1], yp_inout[j + 1, i]) + 0.5)
ymax = int(max(yp_inout[j, i], yp_inout[j, i + 1], yp_inout[j + 1, i + 1], yp_inout[j + 1, i]) + 0.5)
ilon = [[xw_in[j, i], xw_in[j, i + 1], xw_in[j + 1, i + 1], xw_in[j + 1, i]][::-1]]
ilat = [[yw_in[j, i], yw_in[j, i + 1], yw_in[j + 1, i + 1], yw_in[j + 1, i]][::-1]]
ilon = np.radians(np.array(ilon))
ilat = np.radians(np.array(ilat))
xmin = max(0, xmin)
xmax = min(nx_out - 1, xmax)
ymin = max(0, ymin)
ymax = min(ny_out - 1, ymax)
for ii in range(xmin, xmax + 1):
for jj in range(ymin, ymax + 1):
olon = [[xw_out[jj, ii], xw_out[jj, ii + 1], xw_out[jj + 1, ii + 1], xw_out[jj + 1, ii]][::-1]]
olat = [[yw_out[jj, ii], yw_out[jj, ii + 1], yw_out[jj + 1, ii + 1], yw_out[jj + 1, ii]][::-1]]
olon = np.radians(np.array(olon))
olat = np.radians(np.array(olat))
# Figure out the fraction of the input pixel that makes it
# to the output pixel at this position.
overlap, _ = _compute_overlap(ilon, ilat, olon, olat)
original, _ = _compute_overlap(olon, olat, olon, olat)
array_new[jj, ii] += array[j, i] * overlap / original
weights[jj, ii] += overlap / original
array_new /= weights
return array_new, weights
# Put together the parameters common both to the serial and parallel implementations. The aca
# function is needed to enforce that the array will be contiguous when passed to the low-level
# raw C function, otherwise Cython might complain.
aca = np.ascontiguousarray
common_func_par = [0, ny_in, nx_out, ny_out, aca(xp_inout), aca(yp_inout),
aca(xw_in), aca(yw_in), aca(xw_out), aca(yw_out), aca(array),
shape_out]
if nproc == 1:
array_new, weights = _reproject_slice([0, nx_in] + common_func_par)
with np.errstate(invalid='ignore'):
array_new /= weights
return array_new, weights
elif (nproc is None or nproc > 1):
from multiprocessing import Pool, cpu_count
# If needed, establish the number of processors to use.
if nproc is None:
nproc = cpu_count()
# Prime each process in the pool with a small function that disables
# the ctrl+c signal in the child process.
pool = Pool(nproc, _init_worker)
inputs = []
for i in range(nproc):
start = int(nx_in) // nproc * i
end = int(nx_in) if i == nproc - 1 else int(nx_in) // nproc * (i + 1)
inputs.append([start, end] + common_func_par)
results = pool.map(_reproject_slice, inputs)
pool.close()
array_new, weights = zip(*results)
array_new = sum(array_new)
weights = sum(weights)
with np.errstate(invalid='ignore'):
array_new /= weights
return array_new, weights
|