示例#1
0
    def __init__(self, cube, beam=None, mask=None, method="MAD", compute=True):

        # Initialize cube object
        self.cube = SpectralCube.read(cube)

        if mask is not None:
            _check_mask(mask)
        self.mask = mask

        if beam is not None:
            _check_beam(mask)

        # Initialize noise object
        self.noise = Noise(self.cube, beam=beam, method=method)
示例#2
0
def moment_masking(cube, kernel_size, clip=5, dilations=1):
    '''
    '''

    if not signal_id_flag:
        raise ImportError("signal-id is not installed."
                          " This function is not available.")

    smooth_data = convolve(cube.filled_data[:], gauss_kern(kernel_size))

    fake_mask = LazyMask(np.isfinite, cube=cube)

    smooth_cube = SpectralCube(data=smooth_data, wcs=cube.wcs, mask=fake_mask)

    smooth_scale = Noise(smooth_cube).scale

    mask = (smooth_cube > (clip * smooth_scale)).include()

    # Now dilate the mask once

    dilate_struct = nd.generate_binary_structure(3, 3)
    mask = nd.binary_dilation(mask,
                              structure=dilate_struct,
                              iterations=dilations)

    return mask
示例#3
0
    def _update(self, data=None, wcs=None, beam=None, method="MAD"):
        '''
        Helper function to update classes.
        '''

        # Check if we need a new SpectralCube
        if data is None and wcs is None:
            pass
        else:
            if data is None:
                data = self.cube.unmasked_data[:]
            if wcs is None:
                wcs = self.cube.wcs
            # Make new SpectralCube object
            self.cube = SpectralCube(data=data, wcs=wcs)

        if beam is not None:
            _check_beam(beam)
            self.noise = Noise(self.cube, beam=beam, method=method)
示例#4
0
        def __init__(self,
                     cube,
                     beam=None,
                     mask=None,
                     method="MAD",
                     compute=True):

            raise NotImplementedError("SimCube is not yet implemented for "
                                      "general use.")

            # Initialize cube object
            self.cube = SpectralCube.read(cube)

            if mask is not None:
                _check_mask(mask)
            self.mask = mask

            if beam is not None:
                _check_beam(mask)

            # Initialize noise object
            self.noise = Noise(self.cube, beam=beam, method=method)
示例#5
0
    def __init__(self, cube, beam=None, mask=None, method="MAD", compute=True):

        # Initialize cube object
        self.cube = SpectralCube.read(cube)

        if mask is not None:
            _check_mask(mask)
        self.mask = mask

        if beam is not None:
            _check_beam(mask)

        # Initialize noise object
        self.noise = Noise(self.cube, beam=beam, method=method)
示例#6
0
    def __init__(self, cube, mask=None, algorithm=None, beam=None):
        super(ObsCube, self).__init__()
        self.cube = sc.SpectralCube.read(cube)

        self.algorithm = algorithm

        # Make sure mask is an accepted type
        if mask is not None:
            _check_mask(mask)
        self.mask = mask

        if beam is not None:
            _check_beam(beam)
        self.noise = Noise(self.cube, beam=beam)
示例#7
0
    def __init__(self,
                 cube,
                 noise_type='constant',
                 clip=3,
                 scale=None,
                 moment_method='slice'):
        super(Mask_and_Moments, self).__init__()

        if not spectral_cube_flag:
            raise ImportError("Mask_and_Moments requires the spectral-cube "
                              " to be installed: https://github.com/"
                              "radio-astro-tools/spectral-cube")

        if isinstance(cube, SpectralCube):
            self.cube = cube
            self.save_name = None
        else:
            self.cube = SpectralCube.read(cube)
            # Default save name to the cube name without the suffix.
            self.save_name = ".".join(cube.split(".")[:-1])

        self.noise_type = noise_type
        self.clip = clip

        if moment_method not in ['slice', 'cube', 'ray']:
            raise TypeError("Moment method must be 'slice', 'cube', or 'ray'.")
        self.moment_how = moment_method

        if scale is None:
            if not signal_id_flag:
                raise ImportError("signal-id is not installed and error"
                                  " estimation is not available. You must "
                                  "provide the noise scale.")

            self.scale = Noise(self.cube).scale * self.cube.unit
        else:
            if not isinstance(scale, u.Quantity):
                raise TypeError("scale must be a Quantity with the same units"
                                " as the given cube.")
            if not scale.unit == self.cube.unit:
                raise u.UnitsError("scale must have the same units"
                                   " as the given cube.")
            self.scale = scale

        self.prop_headers = None
        self.prop_err_headers = None
示例#8
0
        def __init__(self, cube, mask=None, algorithm=None, beam=None):

            raise NotImplementedError("ObsCube is not yet implemented for "
                                      "general use.")

            super(ObsCube, self).__init__()
            self.cube = SpectralCube.read(cube)

            self.algorithm = algorithm

            # Make sure mask is an accepted type
            if mask is not None:
                _check_mask(mask)
            self.mask = mask

            if beam is not None:
                _check_beam(beam)
            self.noise = Noise(self.cube, beam=beam)
示例#9
0
    def _update(self, data=None, wcs=None, beam=None, method="MAD"):
        '''
        Helper function to update classes.
        '''

        # Check if we need a new SpectralCube
        if data is None and wcs is None:
            pass
        else:
            if data is None:
                data = self.cube.unmasked_data[:]
            if wcs is None:
                wcs = self.cube.wcs
            # Make new SpectralCube object
            self.cube = SpectralCube(data=data, wcs=wcs)

        if beam is not None:
            _check_beam(beam)
            self.noise = Noise(self.cube, beam=beam, method=method)
示例#10
0
    def find_noise(self, return_obj=False):
        '''
        Returns noise estimate, or the whole Noise object.

        Parameters
        ----------
        return_obj : bool, optional
            If True, returns the Noise object. Otherwise returns the estimated
            noise level.
        '''

        if not signal_id_flag:
            raise ImportError("signal-id is not installed."
                              " This function is not available.")

        noise = Noise(self.cube)

        self.scale = noise.scale

        if return_obj:
            return noise

        return noise.scale
    smooth_chans = int(round_up_to_odd(200. / 66.))

    # 10 consecutive channels must be above the MAD level to be real emission.
    num_chans = 7

    peak_snr = 4.5
    # Cutoff level
    min_snr = 3
    # Where to cut at the line edges
    edge_thresh = 0.5

    # Smooth the cube, then create a noise model
    spec_kernel = Box1DKernel(smooth_chans)
    smooth_cube = cube.spectral_smooth(spec_kernel)

    noise = Noise(smooth_cube)
    noise.estimate_noise(spectral_flat=True)
    noise.get_scale_cube()

    snr = noise.snr.copy()

    posns = np.where(snr.max(axis=0) >= min_snr)

    bad_pos = np.where(snr.max(axis=0) < min_snr)
    mask[:, bad_pos[0], bad_pos[1]] = False

    # In case single spectra need to be inspected.
    verbose = False

    for i, j in ProgressBar(zip(*posns)):
示例#12
0
    smooth_chans = int(round_up_to_odd(200. / 66.))

    # 10 consecutive channels must be above the MAD level to be real emission.
    num_chans = 7

    peak_snr = 4.5
    # Cutoff level
    min_snr = 3
    # Where to cut at the line edges
    edge_thresh = 0.5

    # Smooth the cube, then create a noise model
    spec_kernel = Box1DKernel(smooth_chans)
    smooth_cube = cube.spectral_smooth(spec_kernel)

    noise = Noise(smooth_cube)
    noise.estimate_noise(spectral_flat=True)
    noise.get_scale_cube()

    snr = noise.snr.copy()

    posns = np.where(snr.max(axis=0) >= min_snr)

    bad_pos = np.where(snr.max(axis=0) < min_snr)
    mask[:, bad_pos[0], bad_pos[1]] = False

    # In case single spectra need to be inspected.
    verbose = False

    for i, j in ProgressBar(zip(*posns)):
示例#13
0
def make_signal_mask(cube, smooth_chans=200. / 66., min_chan=7, peak_snr=5.,
                     min_snr=3.5, edge_thresh=1.5, verbose=False):
    '''
    Create a robust signal mask by requiring spatial and spectral
    connectivity.
    '''

    import astropy.units as u
    from astropy.convolution import Box1DKernel
    from signal_id import Noise
    from scipy import ndimage as nd
    from astropy.wcs.utils import proj_plane_pixel_scales
    from astropy.utils.console import ProgressBar
    import skimage.morphology as mo
    import numpy as np
    from radio_beam import Beam
    from itertools import groupby, chain
    from operator import itemgetter
    import matplotlib.pyplot as p

    pixscale = proj_plane_pixel_scales(cube.wcs)[0]

    # # Want to smooth the mask edges
    mask = cube.mask.include().copy()

    # Set smoothing parameters and # consecutive channels.
    smooth_chans = int(round_up_to_odd(smooth_chans))

    # consecutive channels to be real emission.
    num_chans = min_chan

    # Smooth the cube, then create a noise model
    spec_kernel = Box1DKernel(smooth_chans)
    smooth_cube = cube.spectral_smooth(spec_kernel)

    noise = Noise(smooth_cube)
    noise.estimate_noise(spectral_flat=True)
    noise.get_scale_cube()

    snr = noise.snr.copy()

    snr[np.isnan(snr)] = 0.0

    posns = np.where(snr.max(axis=0) >= min_snr)

    bad_pos = np.where(snr.max(axis=0) < min_snr)
    mask[:, bad_pos[0], bad_pos[1]] = False

    for i, j in ProgressBar(zip(*posns)):

        # Look for all pixels above min_snr
        good_posns = np.where(snr[:, i, j] > min_snr)[0]

        # Reject if the total is less than connectivity requirement
        if good_posns.size < num_chans:
            mask[:, i, j] = False
            continue

        # Find connected pixels
        sequences = []
        for k, g in groupby(enumerate(good_posns), lambda (i, x): i - x):
            sequences.append(map(itemgetter(1), g))

        # Check length and peak. Require a minimum of 3 pixels above the noise
        # to grow from.
        sequences = [seq for seq in sequences if len(seq) >= 3 and
                     np.nanmax(snr[:, i, j][seq]) >= peak_snr]

        # Continue if no good sequences found
        if len(sequences) == 0:
            mask[:, i, j] = False
            continue

        # Now take each valid sequence and expand the edges until the smoothed
        # spectrum approaches zero.
        edges = [[seq[0], seq[-1]] for seq in sequences]
        for n, edge in enumerate(edges):
            # Lower side
            if n == 0:
                start_posn = edge[0]
                stop_posn = 0
            else:
                start_posn = edge[0] - edges[n - 1][0]
                stop_posn = edges[n - 1][0]

            for pt in np.arange(start_posn, stop_posn, -1):
                # if smoothed[pt] <= mad * edge_thresh:
                if snr[:, i, j][pt] <= edge_thresh:
                    break

                sequences[n].insert(0, pt)

            # Upper side
            start_posn = edge[1]
            if n == len(edges) - 1:
                stop_posn = cube.shape[0]
            else:
                stop_posn = edges[n + 1][0]

            for pt in np.arange(start_posn, stop_posn, 1):
                # if smoothed[pt] <= mad * edge_thresh:
                if snr[:, i, j][pt] <= edge_thresh:
                    break

                sequences[n].insert(0, pt)

        # Final check for the min peak level and ensure all meet the
        # spectral connectivity requirement
        sequences = [seq for seq in sequences if len(seq) >= num_chans and
                     np.nanmax(snr[:, i, j][seq]) >= peak_snr]

        if len(sequences) == 0:
            mask[:, i, j] = False
            continue

        bad_posns = \
            list(set(np.arange(cube.shape[0])) - set(list(chain(*sequences))))

        mask[:, i, j][bad_posns] = False

        if verbose:
            p.subplot(121)
            p.plot(cube.spectral_axis.value, noise.snr[:, i, j])
            min_val = cube.spectral_axis.value[np.where(mask[:, i, j])[0][-1]]
            max_val = cube.spectral_axis.value[np.where(mask[:, i, j])[0][0]]
            p.vlines(min_val, 0,
                     np.nanmax(noise.snr[:, i, j]))
            p.vlines(max_val, 0,
                     np.nanmax(noise.snr[:, i, j]))
            p.plot(cube.spectral_axis.value,
                   noise.snr[:, i, j] * mask[:, i, j], 'bD')

            p.subplot(122)
            p.plot(cube.spectral_axis.value, cube[:, i, j], label='Cube')
            p.plot(cube.spectral_axis.value, smooth_cube[:, i, j],
                   label='Smooth Cube')
            p.axvline(min_val)
            p.axvline(max_val)
            p.plot(cube.spectral_axis.value,
                   smooth_cube[:, i, j] * mask[:, i, j], 'bD')
            p.draw()
            raw_input("Next spectrum?")
            p.clf()
示例#14
0
sub1.show_colorbar()
sub2.show_colorbar()

sub1.colorbar.set_axis_label_text("Intensity (Jy/beam)")
sub2.hide_yaxis_label()

chan_fig.tight_layout()

raw_input("Continue?")
chan_fig.close()

# Now create good masks and derive 0th moments.


noise_cube = Noise(cube)

new_noise = noise_cube.scale

cube = cube.with_mask(cube > new_noise*u.Jy)

old_noise_cube = Noise(old_cube)

old_noise = old_noise_cube.scale

old_cube = old_cube.with_mask(old_cube > old_noise*u.Jy)

# Load in the broad clean mask used
clean_mask = fits.getdata("../../../Arecibo/M33_newmask.fits")

# Need to match the dims
示例#15
0
class SimCube(object):
    '''
    A wrapping class to prepare a simulated spectral data cube for
    comparison with another cube.
    '''

    def __init__(self, cube, beam=None, mask=None, method="MAD", compute=True):

        # Initialize cube object
        self.cube = SpectralCube.read(cube)

        if mask is not None:
            _check_mask(mask)
        self.mask = mask

        if beam is not None:
            _check_beam(mask)

        # Initialize noise object
        self.noise = Noise(self.cube, beam=beam, method=method)

    def add_noise(self):
        '''
        Use Noise to add synthetic noise to the data. Then update
        SpectralCube.
        '''

        # Create the noisy cube
        self.noise.get_noise_cube()
        noise_data = self.noise.noise_cube +\
            self.cube.filled_data[:]

        # Update SpectralCube object
        self._update(data=noise_data)

        return self

    def clean_cube(self, algorithm=None):
        raise NotImplementedError("")

    def apply_mask(self, mask=None):
        '''
        Check if the given mask is acceptable abd apply to
        SpectralCube.
        '''

        # Update mask
        if mask is not None:
            _check_mask(mask)
            self.mask = mask

        # Create the mask, auto masking nan values
        default_mask = np.isfinite(self.cube.filled_data[:])
        if self.mask is not None:
            self.mask = CompositeMask(default_mask, self.mask)
        else:
            self.mask = default_mask

        # Apply mask to spectral cube object
        self.cube = self.cube.with_mask(mask)

        return self

    def _update(self, data=None, wcs=None, beam=None, method="MAD"):
        '''
        Helper function to update classes.
        '''

        # Check if we need a new SpectralCube
        if data is None and wcs is None:
            pass
        else:
            if data is None:
                data = self.cube.unmasked_data[:]
            if wcs is None:
                wcs = self.cube.wcs
            # Make new SpectralCube object
            self.cube = SpectralCube(data=data, wcs=wcs)

        if beam is not None:
            _check_beam(beam)
            self.noise = Noise(self.cube, beam=beam, method=method)

    def compute_properties(self):
        '''
        Use SpectralCube to compute the moments. Also compute the integrated
        intensity based on the noise properties from Noise.
        '''

        self._moment0 = self.cube.moment0().value

        self._moment1 = self.cube.moment1().value

        self._moment2 = self.cube.moment2().value

        _get_int_intensity(self)

        return self

    @property
    def moment0(self):
        return self._moment0

    @property
    def moment1(self):
        return self._moment1

    @property
    def moment2(self):
        return self._moment2

    @property
    def intint(self):
        return self._intint

    def sim_prep(self, mask=None):
        '''
        Prepares the cube when being compared to another simulation.
        This entails:
            * Optionally applying a mask to the data.
            * Computing the cube's property arrays
        '''

        if not mask is None:
            self.apply_mask()

        self.compute_properties()

        return self

    def obs_prep(self, mask=None):
        '''
        Prepares the cube when being compared to observational data.
        This entails:
            * Optionally applying a mask to the data.
            * Add synthetic noise based on the cube's properties.
            * Computing the cube's property arrays
        '''

        if not mask is None:
            self.apply_mask()

        self.add_noise()
        self.compute_properties()

        return self
示例#16
0
class SimCube(object):
    '''
    A wrapping class to prepare a simulated spectral data cube for
    comparison with another cube.
    '''
    def __init__(self, cube, beam=None, mask=None, method="MAD", compute=True):

        # Initialize cube object
        self.cube = SpectralCube.read(cube)

        if mask is not None:
            _check_mask(mask)
        self.mask = mask

        if beam is not None:
            _check_beam(mask)

        # Initialize noise object
        self.noise = Noise(self.cube, beam=beam, method=method)

    def add_noise(self):
        '''
        Use Noise to add synthetic noise to the data. Then update
        SpectralCube.
        '''

        # Create the noisy cube
        self.noise.get_noise_cube()
        noise_data = self.noise.noise_cube +\
            self.cube.filled_data[:]

        # Update SpectralCube object
        self._update(data=noise_data)

        return self

    def clean_cube(self, algorithm=None):
        raise NotImplementedError("")

    def apply_mask(self, mask=None):
        '''
        Check if the given mask is acceptable abd apply to
        SpectralCube.
        '''

        # Update mask
        if mask is not None:
            _check_mask(mask)
            self.mask = mask

        # Create the mask, auto masking nan values
        default_mask = np.isfinite(self.cube.filled_data[:])
        if self.mask is not None:
            self.mask = CompositeMask(default_mask, self.mask)
        else:
            self.mask = default_mask

        # Apply mask to spectral cube object
        self.cube = self.cube.with_mask(mask)

        return self

    def _update(self, data=None, wcs=None, beam=None, method="MAD"):
        '''
        Helper function to update classes.
        '''

        # Check if we need a new SpectralCube
        if data is None and wcs is None:
            pass
        else:
            if data is None:
                data = self.cube.unmasked_data[:]
            if wcs is None:
                wcs = self.cube.wcs
            # Make new SpectralCube object
            self.cube = SpectralCube(data=data, wcs=wcs)

        if beam is not None:
            _check_beam(beam)
            self.noise = Noise(self.cube, beam=beam, method=method)

    def compute_properties(self):
        '''
        Use SpectralCube to compute the moments. Also compute the integrated
        intensity based on the noise properties from Noise.
        '''

        self._moment0 = self.cube.moment0().value

        self._moment1 = self.cube.moment1().value

        self._moment2 = self.cube.moment2().value

        _get_int_intensity(self)

        return self

    @property
    def moment0(self):
        return self._moment0

    @property
    def moment1(self):
        return self._moment1

    @property
    def moment2(self):
        return self._moment2

    @property
    def intint(self):
        return self._intint

    def sim_prep(self, mask=None):
        '''
        Prepares the cube when being compared to another simulation.
        This entails:
            * Optionally applying a mask to the data.
            * Computing the cube's property arrays
        '''

        if not mask is None:
            self.apply_mask()

        self.compute_properties()

        return self

    def obs_prep(self, mask=None):
        '''
        Prepares the cube when being compared to observational data.
        This entails:
            * Optionally applying a mask to the data.
            * Add synthetic noise based on the cube's properties.
            * Computing the cube's property arrays
        '''

        if not mask is None:
            self.apply_mask()

        self.add_noise()
        self.compute_properties()

        return self