Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible fixes to the stacking code #465

Merged
merged 7 commits into from
Feb 7, 2018
16 changes: 13 additions & 3 deletions spectral_cube/analysis_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,22 @@ def stack_spectra(cube, velocity_surface, v0=None,
# Find max +/- pixel shifts, rounding up to the nearest integer
max_pos_shift = np.ceil(np.nanmax(pix_shifts)).astype(int)
max_neg_shift = np.ceil(np.nanmin(pix_shifts)).astype(int)
if max_neg_shift > 0:
# if there are no negative shifts, we can ignore them and just
# use the positive shift
max_neg_shift = 0
if max_pos_shift < 0:
# same for positive
max_pos_shift = 0

# The total pixel size of the new spectral axis
num_vel_pix = cube.spectral_axis.size + max_pos_shift - max_neg_shift
new_header['NAXIS1'] = num_vel_pix

# Adjust CRPIX in header
new_header['CRPIX1'] += max_pos_shift
new_header['CRPIX1'] += -max_neg_shift

pad_size = (max_pos_shift, -max_neg_shift)
pad_size = (-max_neg_shift, max_pos_shift)

else:
pad_size = None
Expand Down Expand Up @@ -269,7 +276,10 @@ def stack_spectra(cube, velocity_surface, v0=None,

all_shifted_spectra.extend([out for out in shifted_spectra])

stacked = stack_function(all_shifted_spectra, axis=0)
shifted_spectra_array = np.array(all_shifted_spectra)
assert shifted_spectra_array.ndim == 2
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for the record, this is to solve a different issue - I once encountered an empty or weirdly shaped all_shifted_spectra, and I want to prevent that. Obviously assertions are not that useful in production code, but it should make future related errors easier to trace.


stacked = stack_function(shifted_spectra_array, axis=0)

stack_spec = \
OneDSpectrum(stacked, unit=cube.unit, wcs=WCS(new_header),
Expand Down
35 changes: 35 additions & 0 deletions spectral_cube/tests/test_analysis_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,41 @@ def test_stacking_wpadding():
or (stacked.size == stack_shape + 1)


def test_padding_direction():

amp = 1.
sigma = 8.
v0 = 0. * u.km / u.s
noise = None
shape = (100, 2, 2)

vel_surface = np.array([[0, 5], [5, 10]])

test_cube, test_vels = \
generate_gaussian_cube(shape=shape, amp=amp, sigma=sigma, noise=noise,
vel_surface=vel_surface)

# Stack the spectra in the cube
stacked = \
stack_spectra(test_cube, test_vels, v0=v0,
stack_function=np.nanmean,
xy_posns=None, num_cores=1,
chunk_size=-1,
progressbar=False, pad_edges=True)

true_spectrum = gaussian(stacked.spectral_axis.value,
amp, v0.value, sigma)

# now check that the stacked spectral axis is right
# (all shifts are negative, so vmin < -50 km/s, should be -60?)
assert stacked.spectral_axis.min() == -60*u.km/u.s
assert stacked.spectral_axis.max() == 49*u.km/u.s

# Calculate residuals
resid = np.abs(stacked.value - true_spectrum)
assert np.std(resid) <= 1e-3


def test_stacking_woffset():
'''
Use a set of identical Gaussian profiles randomly offset to ensure the
Expand Down
9 changes: 6 additions & 3 deletions spectral_cube/tests/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,12 @@ def generate_gaussian_cube(shape=(100, 25, 25), sigma=8., amp=1.,
spat_inds = np.indices(shape[1:])
for y, x in zip(spat_inds[0].flatten(), spat_inds[1].flatten()):
# Lock the mean to within 25% from the centre
mean_pos = \
np.random.uniform(low=spec_inds[spec_quarter],
high=spec_inds[spec_quarter + spec_middle])
if vel_surface is not None:
mean_pos = vel_surface[y,x]
else:
mean_pos = \
np.random.uniform(low=spec_inds[spec_quarter],
high=spec_inds[spec_quarter + spec_middle])
test_cube[:, y, x] = gaussian(spec_inds, amp, mean_pos, sigma)
mean_positions[y, x] = mean_pos + v0
if noise is not None:
Expand Down