Skip to content

Commit 30faba1

Browse files
committed
imaging functions revamp
Need to set polarisation frame in create_image_from_array Added more tests in skycomponent to ensure that the phase definitions are all consistent.
1 parent 3dba130 commit 30faba1

16 files changed

Lines changed: 216 additions & 308 deletions

‎arl/data/data_models.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ def __str__(self):
321321
s += "\tDirection: %s\n" % self.direction
322322
s += "\tShape: %s\n" % self.shape
323323
s += "\tParams: %s\n" % self.params
324-
s += "\tPolarisation frame: %s\n" % self.polarisation_frame.type
324+
s += "\tPolarisation frame: %s\n" % str(self.polarisation_frame.type)
325325
return s
326326

327327

‎arl/image/deconvolution.py‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ def deconvolve_cube(dirty: Image, psf: Image, **kwargs) -> (Image, Image):
125125
else:
126126
log.info("deconvolve_cube: Skipping pol %d, channel %d" % (pol, channel))
127127

128-
comp_image = create_image_from_array(comp_array, dirty.wcs)
129-
residual_image = create_image_from_array(residual_array, dirty.wcs)
128+
comp_image = create_image_from_array(comp_array, dirty.wcs, dirty.polarisation_frame)
129+
residual_image = create_image_from_array(residual_array, dirty.wcs, dirty.polarisation_frame)
130130

131131
elif algorithm == 'msmfsclean' or algorithm == 'mfsmsclean' or algorithm == 'mmclean':
132132
findpeak = get_parameter(kwargs, "findpeak", 'ARL')
@@ -172,8 +172,8 @@ def deconvolve_cube(dirty: Image, psf: Image, **kwargs) -> (Image, Image):
172172
else:
173173
log.info("deconvolve_cube: Skipping pol %d" % (pol))
174174

175-
comp_image = create_image_from_array(comp_array, dirty_taylor.wcs)
176-
residual_image = create_image_from_array(residual_array, dirty_taylor.wcs)
175+
comp_image = create_image_from_array(comp_array, dirty_taylor.wcs, dirty.polarisation_frame)
176+
residual_image = create_image_from_array(residual_array, dirty_taylor.wcs, dirty.polarisation_frame)
177177

178178
return_moments = get_parameter(kwargs, "return_moments", False)
179179
if not return_moments:
@@ -211,8 +211,8 @@ def deconvolve_cube(dirty: Image, psf: Image, **kwargs) -> (Image, Image):
211211
else:
212212
log.info("deconvolve_cube: Skipping pol %d, channel %d" % (pol, channel))
213213

214-
comp_image = create_image_from_array(comp_array, dirty.wcs)
215-
residual_image = create_image_from_array(residual_array, dirty.wcs)
214+
comp_image = create_image_from_array(comp_array, dirty.wcs, dirty.polarisation_frame)
215+
residual_image = create_image_from_array(residual_array, dirty.wcs, dirty.polarisation_frame)
216216
else:
217217
raise ValueError('deconvolve_cube: Unknown algorithm %s' % algorithm)
218218

‎arl/image/iterators.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def image_raster_iter(im: Image, **kwargs) -> Image:
6363
wcs.wcs.crpix[1] -= y
6464

6565
# Yield image from slice (reference!)
66-
yield create_image_from_array(im.data[..., y:y + dy, x:x + dx], wcs)
66+
yield create_image_from_array(im.data[..., y:y + dy, x:x + dx], wcs, im.polarisation_frame)
6767

6868

6969
def image_channel_iter(im: Image, subimages=1) -> Image:
@@ -100,4 +100,4 @@ def image_channel_iter(im: Image, subimages=1) -> Image:
100100
wcs.wcs.crpix[3] -= channel
101101

102102
# Yield image from slice (reference!)
103-
yield create_image_from_array(im.data[channel:channel_max, ...], wcs)
103+
yield create_image_from_array(im.data[channel:channel_max, ...], wcs, im.polarisation_frame)

‎arl/image/operations.py‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ def image_sizeof(im: Image):
3333
return im.size()
3434

3535

36-
def create_image_from_array(data: numpy.array, wcs: WCS = None,
37-
polarisation_frame=PolarisationFrame('stokesI')) -> Image:
36+
def create_image_from_array(data: numpy.array, wcs: WCS, polarisation_frame: PolarisationFrame) -> Image:
3837
""" Create an image from an array and optional wcs
3938
4039
:param data: Numpy.array
@@ -211,7 +210,8 @@ def reproject_image(im: Image, newwcs: WCS, shape=None) -> (Image, Image):
211210
assert isinstance(im, Image), im
212211
rep, foot = reproject_interp((im.data, im.wcs), newwcs, shape, order='bicubic',
213212
independent_celestial_slices=True)
214-
return create_image_from_array(rep, newwcs), create_image_from_array(foot, newwcs)
213+
return create_image_from_array(rep, newwcs, im.polarisation_frame), create_image_from_array(foot, newwcs,
214+
im.polarisation_frame)
215215

216216

217217
def checkwcs(wcs1, wcs2):
@@ -513,7 +513,7 @@ def fft_image(im, template_image=None):
513513
ft_wcs.wcs.cdelt[0] = 1.0 / (ft_shape[3] * d2r * im.wcs.wcs.cdelt[0])
514514
ft_wcs.wcs.cdelt[1] = 1.0 / (ft_shape[2] * d2r * im.wcs.wcs.cdelt[1])
515515
ft_data = ifft(im.data.astype('complex'))
516-
return create_image_from_array(ft_data, wcs=ft_wcs)
516+
return create_image_from_array(ft_data, wcs=ft_wcs, polarisation_frame=im.polarisation_frame)
517517
elif im.wcs.wcs.ctype[0] == 'UU' and im.wcs.wcs.ctype[1] == 'VV':
518518
ft_wcs.wcs.crval[0] = template_image.wcs.wcs.crval[0]
519519
ft_wcs.wcs.crval[1] = template_image.wcs.wcs.crval[1]
@@ -524,7 +524,7 @@ def fft_image(im, template_image=None):
524524
ft_wcs.wcs.cdelt[0] = template_image.wcs.wcs.cdelt[0]
525525
ft_wcs.wcs.cdelt[1] = template_image.wcs.wcs.cdelt[1]
526526
ft_data = fft(im.data.astype('complex'))
527-
return create_image_from_array(ft_data, wcs=ft_wcs)
527+
return create_image_from_array(ft_data, wcs=ft_wcs, polarisation_frame=im.polarisation_frame)
528528
else:
529529
raise NotImplementedError("Cannot FFT specified axes")
530530

@@ -622,7 +622,7 @@ def convert_image_to_kernel(im: Image, oversampling, kernelwidth):
622622
slicex = slice(xend + x, xstart + x, -oversampling)
623623
newdata[chan, pol, y, x, ...] = im.data[chan, pol, slicey, slicex]
624624

625-
return create_image_from_array(newdata, newwcs)
625+
return create_image_from_array(newdata, newwcs, polarisation_frame=im.polarisation_frame)
626626

627627

628628
def create_w_term_like(im: Image, w, phasecentre=None, remove_shift=False, dopol=False) -> Image:

‎arl/imaging/base.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ def shift_vis_to_image(vis: Visibility, im: Image, tangent: bool = True, inverse
6363
# frames is defined.
6464

6565
image_phasecentre = pixel_to_skycoord(nx // 2 + 1, ny // 2 + 1, im.wcs, origin=1)
66+
print("Image phase centre is %s" % str(image_phasecentre))
6667

6768
if vis.phasecentre.separation(image_phasecentre).rad > 1e-15:
6869
if inverse:
@@ -205,15 +206,15 @@ def invert_2d_base(vis: Visibility, im: Image, dopsf: bool = False, normalize: b
205206
if imaginary:
206207
log.debug("invert_2d_base: retaining imaginary part of dirty image")
207208
result = extract_mid(ifft(imgridpad) * gcf, npixel=nx)
208-
resultreal = create_image_from_array(result.real, im.wcs)
209-
resultimag = create_image_from_array(result.imag, im.wcs)
209+
resultreal = create_image_from_array(result.real, im.wcs, im.polarisation_frame)
210+
resultimag = create_image_from_array(result.imag, im.wcs, im.polarisation_frame)
210211
if normalize:
211212
resultreal = normalize_sumwt(resultreal, sumwt)
212213
resultimag = normalize_sumwt(resultimag, sumwt)
213214
return resultreal, sumwt, resultimag
214215
else:
215216
result = extract_mid(numpy.real(ifft(imgridpad)) * gcf, npixel=nx)
216-
resultimage = create_image_from_array(result, im.wcs)
217+
resultimage = create_image_from_array(result, im.wcs, im.polarisation_frame)
217218
if normalize:
218219
resultimage = normalize_sumwt(resultimage, sumwt)
219220
return resultimage, sumwt

‎arl/imaging/params.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,10 +341,10 @@ def pwr23(n):
341341
log.info('advice_wide_field: Number of planes in w stack %d' % (vis_slices))
342342
log.info('advice_wide_field: Number of planes in w projection %d' % wprojection_planes)
343343
if wprojection_planes > 1:
344-
log.info('advice_wide_field: Recommend wprojection gridding')
344+
log.info('advice_wide_field: Recommend that wprojection gridding is used')
345345
kernel = 'wprojection'
346346
else:
347-
log.info('advice_wide_field: Recommend 2d gridding (i.e. no wprojection)')
347+
log.info('advice_wide_field: Recommend that 2d gridding (i.e. no wprojection) is used')
348348
kernel = '2d'
349349

350350
return locals()

‎arl/skycomponent/operations.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def comp_prop(comp, prop_name):
147147
return comps
148148

149149

150-
def apply_beam_to_skycomponent(sc: Union[Skycomponent, List[Skycomponent]], beam: Image, flux_limit=1.0) \
150+
def apply_beam_to_skycomponent(sc: Union[Skycomponent, List[Skycomponent]], beam: Image, flux_limit=0.0) \
151151
-> Union[Skycomponent, List[Skycomponent]]:
152152
""" Insert a Skycomponet into an image
153153
:param beam:

‎arl/util/testing_support.py‎

Lines changed: 21 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
from arl.util.coordinate_support import xyz_at_latitude
5151
from arl.visibility.base import create_blockvisibility
5252
from arl.visibility.coalesce import convert_visibility_to_blockvisibility
53+
from arl.skycomponent.operations import insert_skycomponent
5354

5455
log = logging.getLogger(__name__)
5556

@@ -349,7 +350,8 @@ def create_low_test_image_composite(npixel=16384, polarisation_frame=Polarisatio
349350

350351
def create_low_test_image_from_gleam(npixel=512, polarisation_frame=PolarisationFrame("stokesI"), cellsize=0.000015,
351352
frequency=numpy.array([1e8]), channel_bandwidth=numpy.array([1e6]),
352-
phasecentre=None, kind='cubic', applybeam=False, flux_limit=0.1) -> Image:
353+
phasecentre=None, kind='cubic', applybeam=False, flux_limit=0.1,
354+
radius=None, insert_method='Nearest') -> Image:
353355
"""Create LOW test image from the GLEAM survey
354356
355357
Stokes I is estimated from a cubic spline fit to the measured fluxes. The polarised flux is always zero.
@@ -371,25 +373,21 @@ def create_low_test_image_from_gleam(npixel=512, polarisation_frame=Polarisation
371373
:return: Image
372374
373375
"""
374-
375-
376-
fitsfile = arl_path("data/models/GLEAM_EGC.fits")
377-
378-
hdulist = fits.open(fitsfile, lazy_load_hdus=False)
379-
recs = hdulist[1].data[0].array
380-
ras = recs['RAJ2000']
381-
decs = recs['DEJ2000']
382-
376+
383377
if phasecentre is None:
384378
phasecentre = SkyCoord(ra=+15.0 * u.deg, dec=-35.0 * u.deg, frame='icrs', equinox='J2000')
385-
379+
380+
if radius is None:
381+
radius = npixel * cellsize / numpy.sqrt(2.0)
382+
383+
sc = create_low_test_skycomponents_from_gleam(flux_limit=flux_limit, polarisation_frame=polarisation_frame,
384+
frequency=frequency, phasecentre=phasecentre,
385+
kind=kind, radius=radius)
386386
if polarisation_frame is None:
387387
polarisation_frame = PolarisationFrame("stokesI")
388388

389389
npol = polarisation_frame.npol
390-
391390
nchan = len(frequency)
392-
393391
shape = [nchan, npol, npixel, npixel]
394392
w = WCS(naxis=4)
395393
# The negation in the longitude is needed by definition of RA, DEC
@@ -398,59 +396,18 @@ def create_low_test_image_from_gleam(npixel=512, polarisation_frame=Polarisation
398396
w.wcs.ctype = ["RA---SIN", "DEC--SIN", 'STOKES', 'FREQ']
399397
w.wcs.crval = [phasecentre.ra.deg, phasecentre.dec.deg, 1.0, frequency[0]]
400398
w.naxis = 4
401-
402399
w.wcs.radesys = 'ICRS'
403400
w.wcs.equinox = 2000.0
404401

405402
model = create_image_from_array(numpy.zeros(shape), w, polarisation_frame=polarisation_frame)
406403

407-
p = w.sub(2).wcs_world2pix(numpy.array(ras), numpy.array(decs), 1)
408-
409-
p = numpy.array(p)
410-
mask = numpy.isfinite(p[0, :])
411-
p = [p[0, mask], p[1, mask]]
412-
413-
ip = numpy.round(p).astype('int')
414-
ok = numpy.where((0 <= ip[0, :]) & (npixel > ip[0, :]) & (0 <= ip[1, :]) & (npixel > ip[1, :]))[0]
415-
ps = ip[:, ok]
416-
417-
# For every source, we read all measured fluxes and interpolate to the
418-
# required frequencies
419-
fluxes = []
420-
gleam_freqs = numpy.array([76, 84, 92, 99, 107, 115, 122, 130, 143, 151, 158, 166, 174, 181, 189, 197, 204,
421-
212, 220, 227])
422-
gleam_flux_freq = numpy.zeros([len(ok), len(gleam_freqs)])
423-
for i, f in enumerate(gleam_freqs):
424-
gleam_flux_freq[:,i] = recs['int_flux_%03d' % (f)][:]
425-
404+
model = insert_skycomponent(model, sc, insert_method=insert_method)
426405
if applybeam:
427406
beam = create_low_test_beam(model)
407+
model.data[...] *= beam.data[...]
428408

429-
for source in ok:
409+
log.info(qa_image(model, context='create_low_test_image_from_gleam'))
430410

431-
fint = interpolate.interp1d(gleam_freqs * 1.0e6, gleam_flux_freq[source,:], kind=kind)
432-
factual = fint(frequency)
433-
if applybeam:
434-
factual *= beam.data[:, 0, ip[1, source], ip[0, source]]
435-
436-
fluxes.append(factual)
437-
438-
fluxes = numpy.array(fluxes)
439-
actual_flux = numpy.sum(fluxes)
440-
441-
log.info('create_low_test_image_from_gleam: %d sources inside the image' % (ps.shape[1]))
442-
443-
log.info(
444-
'create_low_test_image_from_gleam: Average flux per channel in image = %.3f' % (actual_flux / float(nchan)))
445-
for iflux, flux in enumerate(fluxes):
446-
if not numpy.isnan(flux).any() and flux.any() > flux_limit:
447-
model.data[:, 0, ps[1, iflux], ps[0, iflux]] = flux[:]
448-
449-
log.info(qa_image(model), context='create_low_test_image_from_gleam')
450-
print(qa_image(model), context='create_low_test_image_from_gleam')
451-
452-
hdulist.close()
453-
454411
return model
455412

456413

@@ -470,6 +427,7 @@ def create_low_test_skycomponents_from_gleam(flux_limit=0.1, polarisation_frame=
470427
catalogue. Hurley-Walker N., et al., Mon. Not. R. Astron. Soc., 464, 1146-1167 (2017), 2017MNRAS.464.1146H
471428
472429
430+
:rtype: Union[None, List[arl.data.data_models.Skycomponent], List]
473431
:param flux_limit: Only write components brighter than this (Jy)
474432
:param polarisation_frame: Polarisation frame (default PolarisationFrame("stokesI"))
475433
:param frequency: Frequencies at which the flux will be estimated
@@ -481,27 +439,26 @@ def create_low_test_skycomponents_from_gleam(flux_limit=0.1, polarisation_frame=
481439

482440
fitsfile = arl_path("data/models/GLEAM_EGC.fits")
483441

484-
decmin = phasecentre.dec.to('rad').value - radius/2.0
485-
decmax = phasecentre.dec.to('rad').value + radius/2.0
442+
rad2deg = 180.0/numpy.pi
443+
decmin = phasecentre.dec.to('deg').value - rad2deg * radius/2.0
444+
decmax = phasecentre.dec.to('deg').value + rad2deg * radius/2.0
486445

487446
hdulist = fits.open(fitsfile, lazy_load_hdus=False)
488447
recs = hdulist[1].data[0].array
489-
print("Before filter %s" % recs.shape)
448+
449+
# Do the simple forms of filtering in pyfits. Filtering on radious is done below.
490450
fluxes = recs['peak_flux_wide']
491451

492452
mask = fluxes > flux_limit
493453
filtered_recs = recs[mask]
494-
print("After flux filter %s" % filtered_recs.shape)
495454

496455
decs = filtered_recs['DEJ2000']
497456
mask = decs > decmin
498457
filtered_recs = filtered_recs[mask]
499-
print("After dec min filter %s" % filtered_recs.shape)
500458

501459
decs = filtered_recs['DEJ2000']
502460
mask = decs < decmax
503461
filtered_recs = filtered_recs[mask]
504-
print("After dec max filter %s" % filtered_recs.shape)
505462

506463
ras = filtered_recs['RAJ2000']
507464
decs = filtered_recs['DEJ2000']
@@ -579,7 +536,7 @@ def create_low_test_beam(model: Image) -> Image:
579536
beam2dwcs.wcs.ctype = model.wcs.sub(2).wcs.ctype
580537
model2dwcs.wcs.crpix = [model.shape[2] // 2 + 1, model.shape[3] // 2 + 1]
581538

582-
beam2d = create_image_from_array(beam.data[0, 0, :, :], beam2dwcs)
539+
beam2d = create_image_from_array(beam.data[0, 0, :, :], beam2dwcs, model.polarisation_frame)
583540
reprojected_beam2d, footprint = reproject_image(beam2d, model2dwcs, shape=model2dshape)
584541
assert numpy.max(footprint.data) > 0.0, "No overlap between beam and model"
585542

0 commit comments

Comments
 (0)