Beispiel #1
0
def dem_slope(img, xres_m, yres_m):
    """
    compute the slope of a DEM.
    
    Parameters
    ----------
    img: numpy.ndarray
        the input DEM
    xres_m: int or float
        the x resolution of the DEM in same units as the height values
    yres_m: int or float
        the y resolution of the DEM in same units as the height values

    Returns
    -------

    """
    boundary = 'extend'
    kernel = CustomKernel(np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) / (8. * xres_m))
    xchangerate_array = convolve(img, kernel, normalize_kernel=False, boundary=boundary,
                                 nan_treatment='fill', fill_value=np.nan)
    
    kernel = CustomKernel(np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]]) / (8. * yres_m))
    ychangerate_array = convolve(img, kernel, normalize_kernel=False, boundary=boundary,
                                 nan_treatment='fill', fill_value=np.nan)
    
    slope_radians = np.arctan(np.sqrt(np.square(xchangerate_array) + np.square(ychangerate_array)))
    slope_degrees = np.rad2deg(slope_radians)
    return slope_degrees
Beispiel #2
0
def do_filtering(image, noisemap, matchedfilter, psf):
    from astropy.convolution import CustomKernel
    from astropy.convolution import convolve

    ## add artefact detector
    grad = get_grad_logerror(noisemap)
    mask_1 = grad > 0.25
    mask_2 = np.log10(noisemap) < -2.25
    ind_artefact = np.logical_and(mask_1, mask_2)
    noisemap[ind_artefact] = np.nan

    nanvalues = np.isnan(noisemap) | np.isnan(image)

    # changed from Steve's code so that NaNs are dealt with properly using astropy convolve
    image[nanvalues] = np.nan

    noisemap[nanvalues] = np.nan
    weightmap = 1. / noisemap ** 2.

    norm = np.sum(psf * matchedfilter) / np.sum(matchedfilter ** 2.)
    matchedfilter_kernel = CustomKernel(norm * matchedfilter)
    matchedfilter_kernel_square = CustomKernel((norm * matchedfilter) ** 2)

    print('max filt', np.max(psf))
    conv_image = convolve(image * weightmap, matchedfilter_kernel)
    conv_noise = convolve(weightmap, matchedfilter_kernel_square)
    conv_image = conv_image / conv_noise
    conv_noise = (1. / (conv_noise ** 0.5))

    conv_image[nanvalues] = np.nan
    conv_noise[nanvalues] = np.nan

    conv_image -= np.nanmean(conv_image)  # meansubtraction, ignore, NaN pixels:
    return (conv_image, conv_noise, matchedfilter_kernel)
Beispiel #3
0
def jopa(image, scat_profile):
    """
    Calculate scattering light image and substract it from given file. 
    Science spectrum and standard star spectrum must have the same Y axis 
    bining.
    """
    from tqdm import tqdm
    from scipy.interpolate import interp2d

    img = fits.getdata(image)
    hdr = fits.getheader(image)
    prf = fits.getdata(scat_profile, 'PSF_SCATTERING')

    prfs = prf['PSF_SCAT_Y']
    wcenters = prf['PARS_WAVE_CENTER']
    nbins = wcenters.size

    _, waves = get_waves(hdr)

    f = interp2d(np.arange(prfs.shape[1]), wcenters, prfs)

    scat_image = np.zeros_like(img)

    print("Scattering light for each column...")
    for i in tqdm(range(img.shape[1])):
        if waves[i] <= wcenters[0]:
            kernel = CustomKernel(prfs[0, :])
        elif waves[i] >= wcenters[-1]:
            kernel = CustomKernel(prfs[-1, :])
        else:
            kernel = CustomKernel(f(f.x, waves[i]))

        scat_image[:, i] = convolve(img[:, i],
                                    kernel,
                                    normalize_kernel=False,
                                    boundary='wrap')

    print("Smooth scattering light along the dispersion direction...")
    kern_disp = CustomKernel(np.sum(prfs, axis=0) / nbins)
    for j in tqdm(range(img.shape[0])):
        scat_image[j, :] = convolve(scat_image[j, :],
                                    kernel,
                                    normalize_kernel=True)

    # save file with scattering light
    ofile = image.replace('.fits', '_scatlight.fits')
    print("Write scattering light file: {}".format(ofile))
    hdr['HISTORY'] = ("Create scattering light image based on the {} using "
                      "profile {}".format(image, scat_profile))
    fits.PrimaryHDU(data=scat_image, header=hdr).writeto(ofile, overwrite=True)

    # substract from image
    oimfile = image.replace('.fits', '_scat_substr.fits')
    print("Write image without with substracted scattering light: {}".format(
        oimfile))
    hdr['HISTORY'] = "Substract scattereing light."
    fits.PrimaryHDU(data=img - scat_image, header=hdr).writeto(oimfile,
                                                               overwrite=True)
Beispiel #4
0
def smooth_days(x, y, kernel, ksize, fix):
    """Smooth data (x, y) given parameters kernel, ksize, fix"""
    kernel = kernel.lower()
    if kernel == 'none' or not ksize:
        return x, y
    if kernel == 'box':
        from astropy.convolution import convolve, Box1DKernel
        ysm = convolve(y, Box1DKernel(ksize), boundary='extend')
    elif kernel == 'gaussian':
        from astropy.convolution import convolve, Gaussian1DKernel
        ysm = convolve(y, Gaussian1DKernel(ksize), boundary='extend')
    elif kernel == 'trapezoid':
        from astropy.convolution import convolve, Trapezoid1DKernel
        ysm = convolve(y, Trapezoid1DKernel(ksize), boundary='extend')
    elif kernel == 'triangle':
        from astropy.convolution import convolve, CustomKernel
        f = triangle(ksize)
        ysm = convolve(y, CustomKernel(f), boundary='extend')
    else:
        raise ValueError('{} not supported.'.format(kernel))
    redo = int(np.floor(ksize / 2))
    xsm = x
    if fix == 'cull':
        _sfs = slice(0, len(ysm) - redo)
        xsm = x[_sfs]
        ysm = ysm[_sfs]
    elif fix == 'redo':
        for i in range(len(y) - redo, len(y)):
            ave = 0.0
            cnt = 0
            for j in range(i, len(y)):
                ave += y[j]
                cnt += 1
            ysm[i] = (ave / cnt + ysm[i]) / 2.0
    return xsm, ysm
Beispiel #5
0
def dem_aspect(img):
    """
    compute the aspect of a DEM.
    
    Parameters
    ----------
    img: numpy.ndarray
        the DEM array

    Returns
    -------
    numpy.ndarray
        the computed aspect array
    """
    boundary = 'extend'
    kernel = CustomKernel(np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) / 8.)
    xchangerate_array = -convolve(img,
                                  kernel,
                                  normalize_kernel=False,
                                  boundary=boundary,
                                  nan_treatment='fill',
                                  fill_value=np.nan)

    kernel = CustomKernel(np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]]) / 8.)
    ychangerate_array = -convolve(img,
                                  kernel,
                                  normalize_kernel=False,
                                  boundary=boundary,
                                  nan_treatment='fill',
                                  fill_value=np.nan)

    aspect = np.rad2deg(np.arctan2(ychangerate_array, -xchangerate_array))
    aspect_value = np.copy(aspect)

    # numpy raises a warning if np.nan values are set to False in a mask
    with np.errstate(invalid='ignore'):
        mask = aspect < 0.0
        aspect_value[mask] = 90.0 - aspect[mask]

        mask = aspect > 90.0
        aspect_value[mask] = 360.0 - aspect[mask] + 90.0

        mask = (aspect >= 0.0) & (aspect < 90.0)
        aspect_value[mask] = 90.0 - aspect[mask]
    return aspect_value
Beispiel #6
0
def output_spectra(spectrum, opacity, filename, longitude, latitude, em_mean,
                   em_std, temp_bright, beam_area, sigma_tau, sigma_tau_smooth,
                   mean):
    """
    Write the spectrum (velocity, flux and opacity) to a votable format file.

    :param spectrum: The spectrum to be output.
    :param opacity:  The opacity to be output.
    :param filename:  The filename to be created
    :param longitude: The galactic longitude of the target object
    :param latitude: The galactic latitude of the target object
    """
    table = Table(meta={'name': filename, 'id': 'opacity'})
    table.add_column(Column(name='plane', data=spectrum.plane))
    table.add_column(
        Column(name='velocity',
               data=spectrum.velocity,
               unit='m/s',
               description='velocity relative to LSRK'))
    table.add_column(Column(name='opacity', data=opacity))

    #following smooth should be using same parameter with line 950
    hann_window = np.hanning(31)
    hann_kernel = CustomKernel(hann_window)
    smooth_y = convolve(opacity, hann_kernel, boundary='extend')
    table.add_column(
        Column(name='smooth_opacity',
               data=smooth_y,
               description='opacity smooth with hanning window 31 channels.'))

    table.add_column(
        Column(name='flux',
               data=spectrum.flux,
               unit='Jy',
               description='Flux per beam'))
    table.add_column(Column(name='temp_brightness', data=temp_bright,
                            unit='K'))
    table.add_column(
        Column(
            name='sigma_tau',
            data=sigma_tau,
            description='Noise in the absorption profile, before smoothing'))
    table.add_column(
        Column(name='sigma_tau_smooth',
               data=sigma_tau_smooth,
               description='Noise in the absorption profile, after smoothing'))
    if len(em_mean) > 0:
        # The emission may not be available, so don't include it if not
        table.add_column(Column(name='em_mean', data=em_mean, unit='K'))
        table.add_column(Column(name='em_std', data=em_std, unit='K'))

    votable = from_table(table)
    votable.infos.append(Info('ra', 'longitude', longitude.value))
    votable.infos.append(Info('dec', 'latitude', latitude.value))
    votable.infos.append(Info('beam_area', 'beam_area', beam_area))
    votable.infos.append(Info('cont', 'continuum', mean))
    writeto(votable, filename)
Beispiel #7
0
def plot_em_abs(em_mean, em_std, opacity, sigma_tau_smooth, filename, CDELT3,
                CRVAL3):
    # read in the emission and absorption spectra and
    # plot an emission-absortion diagram

    if len(em_mean) == 0:
        if os.path.exists(filename):
            os.remove(filename)
        return

    #smooth the spectrum with hanning of 31 channels (1.6 km/s)
    hann_window = np.hanning(31)
    hann_kernel = CustomKernel(hann_window)
    smooth_opacity = convolve(opacity, hann_kernel, boundary='extend')
    smooth_abs = 1.0 - smooth_opacity

    good = np.where(smooth_abs > (3.0 * sigma_tau_smooth))

    super_good = np.where(smooth_abs > (5.0 * sigma_tau_smooth))
    #print('sigma_tau_smooth=',sigma_tau_smooth)
    #print('super_good',super_good)
    sg = np.ravel(np.array(super_good))
    #print('sg=',sg)
    velo = CRVAL3 + (sg + 10) * CDELT3  #revised 20181023
    velo = np.around(velo, decimals=1)
    #print('velo',velo)
    nsuper = len(sg)

    fig = plt.figure()
    plt.plot(smooth_abs[good],
             em_mean[good],
             color='lightsteelblue',
             markerfacecolor='blue',
             markeredgecolor='black',
             marker='.')

    plt.plot(smooth_abs[super_good],
             em_mean[super_good],
             markeredgecolor='deeppink',
             markerfacecolor='black',
             marker='.',
             linestyle='')

    ax = fig.add_subplot(111)
    for i in np.arange(nsuper):
        if (velo[i] % 1) == 0:
            ax.annotate('%s' % velo[i],
                        xy=(smooth_abs[sg[i]], em_mean[sg[i]]),
                        textcoords='data')

    plt.xlabel(r'1-$e^{(-\tau)}$')
    plt.ylabel(r'$T_B$ (K)')
    plt.grid(True)
    plt.savefig(filename)
    #plt.show()
    plt.close()
    return
def make_Gaussian_beam_kernel(header,oversampling):
	bmaj = np.abs(header['BMAJ']/header['CDELT1'])/(2*np.sqrt(2*np.log(2)))
	bmin = np.abs(header['BMIN']/header['CDELT2'])/(2*np.sqrt(2*np.log(2)))
	bpa = header['BPA']+90.
	size = int(oversampling*bmaj)
	if size % 2 == 0:## to catch non odd kernels
		size = size +1
	gauss = makeGaussian_bpa(size=size,amplitude=1, std=[bmaj,bmin], bpa=bpa,center=None)
	np.save('Gauss_model.npy',gauss)
	return CustomKernel(gauss)
Beispiel #9
0
def plot_spectrum(x, y, filename, title, sigma_tau, sigma_tau_smooth):
    """
    Output a plot of opacity vs LSR velocity to a specified file.

    :param x: The velocity data
    :param y: The opacity values for each velocity step
    :param rms: array of channel RMS values
    :param filename: The file the plot should be written to. Should be
         an .eps or .pdf file.
    :param title: The title for the plot
    :param con_start_vel: The minimum velocity that the continuum was measured at.
    :param con_end_vel: The maximum velocity that the continuum was measured at.
    """
    fig = plt.figure()
    plt.plot(x / 1000, y, color='gray', zorder=2)

    #overplot a smoothed spectrum
    #smooth the spectrum with hanning of 31 channels (1.6 km/s)
    hann_window = np.hanning(31)
    hann_kernel = CustomKernel(hann_window)
    smooth_y = convolve(y, hann_kernel, boundary='extend')
    plt.plot(x / 1000, smooth_y, color='blue', zorder=4)

    if len(sigma_tau) > 0:
        tau_max = 1 + sigma_tau
        tau_min = 1 - sigma_tau
        plt.fill_between(x / 1000,
                         tau_min,
                         tau_max,
                         facecolor='silver',
                         color='silver',
                         alpha=0.75,
                         zorder=1)
        tau_max_smooth = 1 + sigma_tau_smooth
        tau_min_smooth = 1 - sigma_tau_smooth
        plt.fill_between(x / 1000,
                         tau_min_smooth,
                         tau_max_smooth,
                         facecolor='cornflowerblue',
                         color='cornflowerblue',
                         zorder=3,
                         alpha=0.5)

    plt.axhline(1, color='black')

    plt.xlabel(r'Velocity (km/s)')
    plt.ylabel(r'$e^{(-\tau)}$')
    plt.title(title)
    plt.grid(True)
    plt.savefig(filename)
    #plt.show()
    plt.close()
    return
Beispiel #10
0
def fft_2d_hanning(mask, size=2):

    assert np.min(mask.shape) > size * 2 + 1
    assert size > 1

    idx = np.linspace(-0.5, 0.5, size * 2 + 1, endpoint=True)
    xx, yy = np.meshgrid(idx, idx)
    n = np.sqrt(xx ** 2 + yy ** 2)
    hann_kernel = (1 + np.cos(2 * np.pi * n)) / 2
    hann_kernel[n > 0.5] = 0

    hann_kernel = CustomKernel(hann_kernel)
    hann_kernel.normalize("integral")

    # Reduce mask size to apodize on the edge
    apod = ~shrink_mask(mask, hann_kernel)

    # Final convolution goes to 0 on the edge
    apod = convolve_fft(apod, hann_kernel)

    return apod
Beispiel #11
0
    def optical_depth(self):
        tau_array = -np.log(self.T_B / self.T_bg)
        tau_noise = round(np.std(tau_array[self.vmin_ind:self.vmax_ind + 1]),
                          3)

        self.tau_peak = max(tau_array)
        self.tau = tau_array
        self.tau_noise = tau_noise
        self.tau_raw = tau_array
        self.opacity = 1 - np.exp(-1 * self.tau_raw)

        # Katie's awesome (hanning) smoothing, width is 5 velocity channels wide
        hanning_sz = 5
        hann_window = np.hanning(hanning_sz)
        hann_kernel = CustomKernel(hann_window)
        self.tau = convolve(self.tau, hann_kernel, boundary='extend')
Beispiel #12
0
def get_mean_continuum(spectrum):
    """
    Calculate the mean of the continuum values. This is based on precalculated regions where there is no gas expected.
    :param spectrum: The spectrum to be analysed, should be a numpy array of
        plane, velocity and flux values.
    :return: A single float which is the mean continuum flux.
    """

    # velocities = spectrum.velocity
    # velo1=-123.063627344+(start_channel+50)*0.103056351495
    # velo2=-123.063627344+(start_channel+300)*0.103056351495
    # velo3=-123.063627344+(start_channel+1700)*0.103056351495
    # velo4=-123.063627344+(start_channel+1950)*0.103056351495
    # continuum_range = np.where(((velocities>velo1*1000.)&(velocities<velo2*1000.))|((velocities>velo3*1000.)&(velocities<velo4*1000.)))

    #
    # # print ("...gave sample of", continuum_sample)
    # mean_cont = np.nanmean(continuum_sample)

    print("len(spectrum.flux[:])", len(spectrum.flux[:]))
    channelno = np.arange(len(spectrum.flux[:]))
    continuum_range = np.where((channelno < 260) | (channelno > 740))
    x = np.ravel(continuum_range)
    print("shape(x)", np.shape(x))
    continuum_sample = spectrum.flux[continuum_range]
    y = np.ravel(continuum_sample)
    print("shape(y)", np.shape(y))
    mean_cont = np.nanmean(continuum_sample)
    print("mean_cont", mean_cont)

    opacity_sample = continuum_sample / mean_cont
    sd_cont = np.std(opacity_sample)

    #same with line 950
    hann_window = np.hanning(31)
    hann_kernel = CustomKernel(hann_window)
    smooth_opacity_sample = convolve(opacity_sample,
                                     hann_kernel,
                                     boundary='extend')
    sd_cont_smooth = np.nanstd(smooth_opacity_sample)

    print("Found standard deviation of the smoothed spectrum of {}".format(
        sd_cont_smooth))

    return mean_cont, sd_cont, sd_cont_smooth
Beispiel #13
0
def interpolate(img: CCDData):
    """
    Takes a image with a mask for bad pixels and interpolates over the bad pixels

    :param img: the image you want to interpolate bad pixels in
    :return: interpolated image

    """
    # TODO combiner does not care about this and marks it invalid still
    from astropy.convolution import CustomKernel
    from astropy.convolution import interpolate_replace_nans

    # TODO this here doesn't really work all that well -> extended regions cause artifacts at border
    kernel_array = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]
                             ]) / 9  # average of all surrounding pixels
    # noinspection PyTypeChecker
    kernel = CustomKernel(
        kernel_array
    )  # TODO the original pipeline used fixpix, which says it uses linear interpolation

    img.data[np.logical_not(img.mask)] = np.NaN
    img.data = interpolate_replace_nans(img.data, kernel)

    return img
Beispiel #14
0
    def set_smoothing_kernel(self,
                             kernel=None,
                             kernel_width=None,
                             custom_array_kernel=None,
                             custom_kernel_function=None,
                             function_array_size=21):
        #if custom_kernel_array is None and custom_kernel_function is None:

        if custom_array_kernel is not None:
            custom_kernel_array = np.array([i for i in custom_array_kernel])
            self.kernel_func = CustomKernel(custom_kernel_array)
            self.kernel_func_type = SmoothingKernels.CUSTOM

        elif custom_kernel_function is not None:
            if isinstance(custom_kernel_function, Fittable1DModel):
                self.kernel_func = Model1DKernel(custom_kernel_function,
                                                 x_size=function_array_size)
            else:
                self.kernel_func = custom_kernel_function

            self.kernel_func_type = SmoothingKernels.CUSTOM

        elif kernel in default_smoothing_kernels:
            width = int(kernel_width)
            if kernel == SmoothingKernels.GAUSSIAN1D:
                self.kernel_func = Gaussian1DKernel(width)
            elif kernel == SmoothingKernels.Box1D:
                self.kernel_func = Box1DKernel(width)
            elif kernel == SmoothingKernels.MEDIAN:
                self.kernel_func = ndimage.median_filter
            else:
                raise Exception("Unsupported smoothing kernel " + str(kernel))
            self.kernel_func_type = kernel
            self.kernel_width = width
        else:
            raise Exception("Problem while setting the smoothing kernel")
Beispiel #15
0
    def run(self, maps, kernel, which="all", downsampling_factor=None):
        """
        Run TS map estimation.

        Requires `counts`, `exposure` and `background` map to run.

        Parameters
        ----------
        maps : dict
            Input sky maps.
        kernel : `astropy.convolution.Kernel2D` or 2D `~numpy.ndarray`
            Source model kernel.
        which : list of str or 'all'
            Which maps to compute.
        downsampling_factor : int
            Sample down the input maps to speed up the computation. Only integer
            values that are a multiple of 2 are allowed. Note that the kernel is
            not sampled down, but must be provided with the downsampled bin size.

        Returns
        -------
        maps : dict
            Result maps.
        """
        p = self.parameters

        if (np.array(kernel.shape) > np.array(
                maps["counts"].data.shape)).any():
            raise ValueError(
                "Kernel shape larger than map shape, please adjust"
                " size of the kernel")

        if downsampling_factor:
            shape = maps["counts"].data.shape
            pad_width = symmetric_crop_pad_width(shape, shape_2N(shape))[0]

            for name in maps:
                maps[name] = maps[name].pad(pad_width)
                preserve_counts = name in ["counts", "background", "exclusion"]
                maps[name] = maps[name].downsample(
                    downsampling_factor, preserve_counts=preserve_counts)

        if not isinstance(kernel, Kernel2D):
            kernel = CustomKernel(kernel)

        if which == "all":
            which = ["ts", "sqrt_ts", "flux", "flux_err", "flux_ul", "niter"]

        result = {}
        for name in which:
            data = np.nan * np.ones_like(maps["counts"].data)
            result[name] = maps["counts"].copy(data=data)

        mask = self.mask_default(maps, kernel)

        if "mask" in maps:
            mask.data &= maps["mask"].data

        if p["threshold"] or p["method"] == "root newton":
            flux = self.flux_default(maps, kernel).data
        else:
            flux = None

        # prepare dtype for cython methods
        counts = maps["counts"].data.astype(float)
        background = maps["background"].data.astype(float)
        exposure = maps["exposure"].data.astype(float)

        # Compute null statistics per pixel for the whole image
        c_0 = _cash_cython(counts, background)

        error_method = p["error_method"] if "flux_err" in which else "none"
        ul_method = p["ul_method"] if "flux_ul" in which else "none"

        wrap = partial(
            _ts_value,
            counts=counts,
            exposure=exposure,
            background=background,
            c_0=c_0,
            kernel=kernel,
            flux=flux,
            method=p["method"],
            error_method=error_method,
            threshold=p["threshold"],
            error_sigma=p["error_sigma"],
            ul_method=ul_method,
            ul_sigma=p["ul_sigma"],
            rtol=p["rtol"],
        )

        x, y = np.where(mask.data)
        positions = list(zip(x, y))

        with contextlib.closing(Pool(processes=p["n_jobs"])) as pool:
            log.info("Using {} jobs to compute TS map.".format(p["n_jobs"]))
            results = pool.map(wrap, positions)

        # Set TS values at given positions
        j, i = zip(*positions)
        for name in ["ts", "flux", "niter"]:
            result[name].data[j, i] = [_[name] for _ in results]

        if "flux_err" in which:
            result["flux_err"].data[j, i] = [_["flux_err"] for _ in results]

        if "flux_ul" in which:
            result["flux_ul"].data[j, i] = [_["flux_ul"] for _ in results]

        # Compute sqrt(TS) values
        if "sqrt_ts" in which:
            result["sqrt_ts"] = self.sqrt_ts(result["ts"])

        if downsampling_factor:
            for name in which:
                order = 0 if name == "niter" else 1
                result[name] = result[name].upsample(
                    factor=downsampling_factor,
                    preserve_counts=False,
                    order=order)
                result[name] = result[name].crop(crop_width=pad_width)

        return result
Beispiel #16
0
 def _estimate_significance(self, counts, background):
     kernel = CustomKernel(self.kernel_src)
     images = compute_lima_image(counts, background, kernel=kernel)
     return images["significance"]
Beispiel #17
0
    def run(self, dataset, kernel, which="all", downsampling_factor=None):
        """
        Run TS map estimation.

        Requires a MapDataset with counts, exposure and background_model
        properly set to run.

        Parameters
        ----------
        kernel : `astropy.convolution.Kernel2D` or 2D `~numpy.ndarray`
            Source model kernel.
        which : list of str or 'all'
            Which maps to compute.
        downsampling_factor : int
            Sample down the input maps to speed up the computation. Only integer
            values that are a multiple of 2 are allowed. Note that the kernel is
            not sampled down, but must be provided with the downsampled bin size.

        Returns
        -------
        maps : dict
            Result maps.
        """
        p = self.parameters

        if (np.array(kernel.shape) > np.array(dataset.counts.data.shape[1:])).any():
            raise ValueError(
                "Kernel shape larger than map shape, please adjust"
                " size of the kernel"
            )

        # First create 2D map arrays
        counts = dataset.counts.sum_over_axes(keepdims=False)
        background = dataset.npred().sum_over_axes(keepdims=False)
        exposure = dataset.exposure.sum_over_axes(keepdims=False)
        if dataset.mask is not None:
            mask = counts.copy(data=(dataset.mask.sum(axis=0) > 0).astype("int"))
        else:
            mask = counts.copy(data=np.ones_like(counts).astype("int"))

        if downsampling_factor:
            shape = counts.data.shape
            pad_width = symmetric_crop_pad_width(shape, shape_2N(shape))[0]

            counts = counts.pad(pad_width).downsample(
                downsampling_factor, preserve_counts=True
            )
            background = background.pad(pad_width).downsample(
                downsampling_factor, preserve_counts=True
            )
            exposure = exposure.pad(pad_width).downsample(
                downsampling_factor, preserve_counts=False
            )
            mask = mask.pad(pad_width).downsample(
                downsampling_factor, preserve_counts=False
            )
            mask.data = mask.data.astype("int")

        mask.data &= self.mask_default(exposure, background, kernel).data

        if not isinstance(kernel, Kernel2D):
            kernel = CustomKernel(kernel)

        if which == "all":
            which = ["ts", "sqrt_ts", "flux", "flux_err", "flux_ul", "niter"]

        result = {}
        for name in which:
            data = np.nan * np.ones_like(counts.data)
            result[name] = counts.copy(data=data)

        flux_map = self.flux_default(dataset, kernel)

        if p["threshold"] or p["method"] == "root newton":
            flux = flux_map.data
        else:
            flux = None

        # prepare dtype for cython methods
        counts_array = counts.data.astype(float)
        background_array = background.data.astype(float)
        exposure_array = exposure.data.astype(float)

        # Compute null statistics per pixel for the whole image
        c_0 = cash(counts_array, background_array)

        error_method = p["error_method"] if "flux_err" in which else "none"
        ul_method = p["ul_method"] if "flux_ul" in which else "none"

        wrap = functools.partial(
            _ts_value,
            counts=counts_array,
            exposure=exposure_array,
            background=background_array,
            c_0=c_0,
            kernel=kernel,
            flux=flux,
            method=p["method"],
            error_method=error_method,
            threshold=p["threshold"],
            error_sigma=p["error_sigma"],
            ul_method=ul_method,
            ul_sigma=p["ul_sigma"],
            rtol=p["rtol"],
        )

        x, y = np.where(np.squeeze(mask.data))
        positions = list(zip(x, y))
        results = list(map(wrap, positions))

        # Set TS values at given positions
        j, i = zip(*positions)
        for name in ["ts", "flux", "niter"]:
            result[name].data[j, i] = [_[name] for _ in results]

        if "flux_err" in which:
            result["flux_err"].data[j, i] = [_["flux_err"] for _ in results]

        if "flux_ul" in which:
            result["flux_ul"].data[j, i] = [_["flux_ul"] for _ in results]

        # Compute sqrt(TS) values
        if "sqrt_ts" in which:
            result["sqrt_ts"] = self.sqrt_ts(result["ts"])

        if downsampling_factor:
            for name in which:
                order = 0 if name == "niter" else 1
                result[name] = result[name].upsample(
                    factor=downsampling_factor, preserve_counts=False, order=order
                )
                result[name] = result[name].crop(crop_width=pad_width)

        # Set correct units
        if "flux" in which:
            result["flux"].unit = flux_map.unit
        if "flux_err" in which:
            result["flux_err"].unit = flux_map.unit
        if "flux_ul" in which:
            result["flux_ul"].unit = flux_map.unit

        return result
Beispiel #18
0
def compute_ts_image(counts,
                     background,
                     exposure,
                     kernel,
                     mask=None,
                     flux=None,
                     method='root brentq',
                     parallel=True,
                     threshold=None):
    """
    Compute TS image using different optimization methods.

    Parameters
    ----------
    counts : `~gammapy.image.SkyImage`
        Counts image.
    background : `~gammapy.image.SkyImage`
        Background image
    exposure : `~gammapy.image.SkyImage`
        Exposure image
    kernel : `astropy.convolution.Kernel2D` or 2D `~numpy.ndarray`
        Source model kernel.
    flux : float (None)
        Flux image used as a starting value for the amplitude fit.
    method : str ('root')
        The following options are available:

        * ``'root brentq'`` (default)
            Fit amplitude finding roots of the the derivative of
            the fit statistics. Described in Appendix A in Stewart (2009).
        * ``'root newton'``
            TODO: document
        * ``'leastsq iter'``
            TODO: document
    parallel : bool (True)
        Whether to use multiple cores for parallel processing.
    threshold : float (None)
        If the TS value corresponding to the initial flux estimate is not above
        this threshold, the optimizing step is omitted to save computing time.

    Returns
    -------
    images : `~gammapy.image.SkyImageList`
        Images (ts, niter, amplitude)

    Notes
    -----
    Negative :math:`TS` values are defined as following:

    .. math::

        TS = \\left \\{
                 \\begin{array}{ll}
                   -TS & : \\textnormal{if} \\ F < 0 \\\\
                   \\ \\ TS & : \\textnormal{else}
                 \\end{array}
               \\right.

    Where :math:`F` is the fitted flux amplitude.

    References
    ----------
    [Stewart2009]_
    """
    t_0 = time()

    log.info("Using method '{}'".format(method))

    if not isinstance(kernel, Kernel2D):
        kernel = CustomKernel(kernel)

    wcs = counts.wcs.deepcopy()

    # Parse data type
    counts = counts.data.astype(float)
    background = background.data.astype(float)
    exposure = exposure.data.astype(float)
    assert counts.shape == background.shape
    assert counts.shape == exposure.shape

    # in some image there are pixels, which have exposure, but zero
    # background, which doesn't make sense and causes the TS computation
    # to fail, this is a temporary fix
    mask_ = np.logical_and(background == 0, exposure > 0)
    if mask_.any():
        log.warning('There are pixels in the data, that have exposure, but '
                    'zero background, which can cause the ts computation to '
                    'fail. Setting exposure of this pixels to zero.')
        exposure[mask_] = 0

    if (flux is None and method != 'root brentq') or threshold is not None:
        from scipy.signal import fftconvolve

        with np.errstate(invalid='ignore', divide='ignore'):
            flux = (counts - background) / exposure / FLUX_FACTOR
        flux[~np.isfinite(flux)] = 0
        flux = fftconvolve(flux, kernel.array, mode='same') / np.sum(
            kernel.array**2)

    # Compute null statistics for the whole image
    c_0_image = _cash_cython(counts, background)

    x_min, x_max = kernel.shape[1] // 2, counts.shape[1] - kernel.shape[1] // 2
    y_min, y_max = kernel.shape[0] // 2, counts.shape[0] - kernel.shape[0] // 2
    positions = product(range(y_min, y_max), range(x_min, x_max))

    # Positions where exposure == 0 are not processed
    if mask is None:
        mask = exposure > 0
    positions = [(j, i) for j, i in positions if mask[j][i]]

    wrap = partial(_ts_value,
                   counts=counts,
                   exposure=exposure,
                   background=background,
                   c_0_image=c_0_image,
                   kernel=kernel,
                   flux=flux,
                   method=method,
                   threshold=threshold)

    if parallel:
        log.info('Using {0} cores to compute TS image.'.format(cpu_count()))
        pool = Pool()
        results = pool.map(wrap, positions)
        pool.close()
        pool.join()
    else:
        results = map(wrap, positions)

    assert positions, (
        "Positions are empty: possibly kernel " +
        "{} is larger than counts {}".format(kernel.shape, counts.shape))

    # Set TS values at given positions
    j, i = zip(*positions)
    ts = np.ones(counts.shape) * np.nan
    amplitudes = np.ones(counts.shape) * np.nan
    niter = np.ones(counts.shape) * np.nan
    ts[j, i] = [_[0] for _ in results]
    amplitudes[j, i] = [_[1] for _ in results]
    niter[j, i] = [_[2] for _ in results]

    # Handle negative TS values
    with np.errstate(invalid='ignore', divide='ignore'):
        sqrt_ts = np.where(ts > 0, np.sqrt(ts), -np.sqrt(-ts))

    runtime = np.round(time() - t_0, 2)
    meta = OrderedDict(runtime=runtime)
    return SkyImageList([
        SkyImage(name='ts', data=ts.astype('float32'), wcs=wcs),
        SkyImage(name='sqrt_ts', data=sqrt_ts.astype('float32'), wcs=wcs),
        SkyImage(name='amplitude', data=amplitudes.astype('float32'), wcs=wcs),
        SkyImage(name='niter', data=niter.astype('int16'), wcs=wcs),
    ],
                        meta=meta)
Beispiel #19
0
# Example with a few sources
#sources = create_sources.multiple(br=[1.0,0.5,0.3,0.1],Dec_offset=[0.1,-0.2,0.3,-0.4],\
#RA_offset=[0.1,-0.3,0.35,0.5],imsize=imsize,pixscale=pixscale)

# Fill in point sources
for source in sources:
    data[sources[source]['Dec'],
         sources[source]['RA']] = sources[source]['Brightness']

# Write model image with point sources to fits
fits.writeto('model.fits', data, overwrite=True)

# Create custom convolution Kernel from PSF
try:
    psf_kern = CustomKernel(psf_data)
except:
    print('Adding dummy row and column to psf data for CustomKernel to work.')
    psfnpix_y = psf_data.shape[0] + 1
    psfnpix_x = psf_data.shape[1] + 1
    new_psf = np.zeros((psfnpix_y, psfnpix_x), dtype=np.float64)
    new_psf[:psfnpix_y - 1, :psfnpix_x - 1] = psf_data
    #hdu_new_psf = fits.PrimaryHDU(new_psf)
    psf_header['NAXIS1'] = psfnpix_y
    psf_header['NAXIS2'] = psfnpix_x
    fits.writeto('new_psf.fits', new_psf, psf_header, overwrite=True)
    psf_kern = CustomKernel(new_psf)

#Convolve model image with PSF and save FITS file
convl_image = convolve_fft(data, psf_kern, allow_huge=True)
im_head = psf_header
        print mtp

    base_year = projection_year
    # pop2=scenario_subset['TotalPop_IIASA'].ix[projection_year,scenario]
    pop2_urban = scenario_subset['UrbanPop'].ix[projection_year, scenario]
    pop2_rural = scenario_subset['RuralPop'].ix[projection_year, scenario]
    print 'projected urban population number for ', projection_year, 'is ', pop2_urban
    print 'projected rural population number for ', projection_year, 'is ', pop2_rural

    pop1_urban = np.sum(mup)
    urb_pop_change = pop2_urban - pop1_urban

    pop1_rural = np.sum(mrp)
    rur_pop_change = pop2_rural - pop1_rural

    astropy_kernel1 = CustomKernel(
        urban_window)  ## astropy uses object kernels
    astropy_kernel2 = CustomKernel(rural_window)
    ### ---This is where the potential for each cell is calculated---------------------------------------------------------------------------------------------###
    urban_convolved = np.add(convolve(mtp, astropy_kernel1),
                             np.power(mtp, urban_alpha))
    rural_convolved = np.add(
        convolve(mtp, astropy_kernel2), np.power(mtp, rural_alpha)
    )  ## inner parenthesis in surface formula + itself in the power of cell-specific alpha
    urban_potential = mm * urban_convolved
    rural_potential = mm * rural_convolved
    print 'pop change between base and projection year=', rur_pop_change + urb_pop_change
    ###--------------------------------------------------------------------------------------------------------------------------------------------------------###
    if urb_pop_change > 0:
        urban_total_potential = urban_potential.sum()
        urban_pot_surface = urban_potential / urban_total_potential
        urban_projected_surface = mup + (
Beispiel #21
0
    def run(self, images, kernel, which='all'):
        """
        Run TS image estimation.

        Requires `counts`, `exposure` and `background` image to run.

        Parameters
        ----------
        kernel : `astropy.convolution.Kernel2D` or 2D `~numpy.ndarray`
            Source model kernel.
        images : `SkyImageList`
            List of input sky images.
        which : list of str or 'all'
            Which images to compute.

        Returns
        -------
        images : `~gammapy.image.SkyImageList`
            Result images.

        """
        t_0 = time()
        images.check_required(['counts', 'background', 'exposure'])
        p = self.parameters

        result = SkyImageList()

        if not isinstance(kernel, Kernel2D):
            kernel = CustomKernel(kernel)

        if which == 'all':
            which = ['ts', 'sqrt_ts', 'flux', 'flux_err', 'flux_ul', 'niter']

        for name in which:
            result[name] = SkyImage.empty_like(images['counts'], fill=np.nan)

        mask = self.mask_default(images, kernel)

        if 'mask' in images.names:
            mask.data &= images['mask'].data

        x, y = np.where(mask)
        positions = list(zip(x, y))

        if p['method'] == 'root newton':
            flux = self.flux_default(images, kernel).data
        else:
            flux = None

        # prpare dtype for cython methods
        counts = images['counts'].data.astype(float)
        background = images['background'].data.astype(float)
        exposure = images['exposure'].data.astype(float)

        # Compute null statistics for the whole image
        c_0_image = _cash_cython(counts, background)

        error_method = p['error_method'] if 'flux_err' in which else 'none'
        ul_method = p['ul_method'] if 'flux_ul' in which else 'none'

        wrap = partial(_ts_value,
                       counts=counts,
                       exposure=exposure,
                       background=background,
                       c_0_image=c_0_image,
                       kernel=kernel,
                       flux=flux,
                       method=p['method'],
                       error_method=error_method,
                       threshold=p['threshold'],
                       error_sigma=p['error_sigma'],
                       ul_method=ul_method,
                       ul_sigma=p['ul_sigma'],
                       rtol=p['rtol'])

        if p['parallel']:
            log.info('Using {} cores to compute TS image.'.format(cpu_count()))
            pool = Pool()
            results = pool.map(wrap, positions)
            pool.close()
            pool.join()
        else:
            results = map(wrap, positions)

        # Set TS values at given positions
        j, i = zip(*positions)
        for name in ['ts', 'flux', 'niter']:
            result[name].data[j, i] = [_[name] for _ in results]

        if 'flux_err' in which:
            result['flux_err'].data[j, i] = [_['flux_err'] for _ in results]

        if 'flux_ul' in which:
            result['flux_ul'].data[j, i] = [_['flux_ul'] for _ in results]

        # Compute sqrt(TS) values
        if 'sqrt_ts' in which:
            result['sqrt_ts'] = self.sqrt_ts(result['ts'])

        runtime = np.round(time() - t_0, 2)
        result.meta = OrderedDict(runtime=runtime)
        return result
Beispiel #22
0
    def run(self, maps, kernel, which='all', downsampling_factor=None):
        """
        Run TS map estimation.

        Requires `counts`, `exposure` and `background` map to run.

        Parameters
        ----------
        kernel : `astropy.convolution.Kernel2D` or 2D `~numpy.ndarray`
            Source model kernel.
        maps : `OrderedDict`
            List of input sky maps.
        which : list of str or 'all'
            Which maps to compute.
        downsampling_factor : int
            Sample down the input maps to speed up the computation. Only integer
            values that are a multiple of 2 are allowed. Note that the kernel is
            not sampled down, but must be provided with the downsampled bin size.

        Returns
        -------
        maps : `OrderedDict`
            Result maps.
        """
        p = self.parameters

        if downsampling_factor:
            shape = maps['counts'].data.shape
            pad_width = symmetric_crop_pad_width(shape, shape_2N(shape))[0]

            for name in maps:
                maps[name] = maps[name].pad(pad_width)
                preserve_counts = name in ['counts', 'background', 'exclusion']
                maps[name] = maps[name].downsample(downsampling_factor,
                                            preserve_counts=preserve_counts)

        if not isinstance(kernel, Kernel2D):
            kernel = CustomKernel(kernel)

        if which == 'all':
            which = ['ts', 'sqrt_ts', 'flux', 'flux_err', 'flux_ul', 'niter']

        result = OrderedDict()
        for name in which:
            data = np.nan * np.ones_like(maps['counts'].data)
            result[name] = maps['counts'].copy(data=data)

        mask = self.mask_default(maps, kernel)

        if 'mask' in maps:
            mask.data &= maps['mask'].data

        if p['method'] == 'root newton':
            flux = self.flux_default(maps, kernel).data
        else:
            flux = None

        # prepare dtype for cython methods
        counts = maps['counts'].data.astype(float)
        background = maps['background'].data.astype(float)
        exposure = maps['exposure'].data.astype(float)

        # Compute null statistics per pixel for the whole image
        c_0 = _cash_cython(counts, background)

        error_method = p['error_method'] if 'flux_err' in which else 'none'
        ul_method = p['ul_method'] if 'flux_ul' in which else 'none'

        wrap = partial(
            _ts_value,
            counts=counts,
            exposure=exposure,
            background=background,
            c_0=c_0,
            kernel=kernel,
            flux=flux,
            method=p['method'],
            error_method=error_method,
            threshold=p['threshold'],
            error_sigma=p['error_sigma'],
            ul_method=ul_method,
            ul_sigma=p['ul_sigma'],
            rtol=p['rtol']
            )


        x, y = np.where(mask.data)
        positions = list(zip(x, y))

        with contextlib.closing(Pool(processes=p['n_jobs'])) as pool:
            log.info('Using {} jobs to compute TS map.'.format(p['n_jobs']))
            results = pool.map(wrap, positions)

        # Set TS values at given positions
        j, i = zip(*positions)
        for name in ['ts', 'flux', 'niter']:
            result[name].data[j, i] = [_[name] for _ in results]

        if 'flux_err' in which:
            result['flux_err'].data[j, i] = [_['flux_err'] for _ in results]

        if 'flux_ul' in which:
            result['flux_ul'].data[j, i] = [_['flux_ul'] for _ in results]

        # Compute sqrt(TS) values
        if 'sqrt_ts' in which:
            result['sqrt_ts'] = self.sqrt_ts(result['ts'])

        if downsampling_factor:
            for name in which:
                order = 0 if name == 'niter' else 1
                result[name] = result[name].upsample(
                    factor=downsampling_factor,
                    preserve_counts=False,
                    order=order
                    )
                result[name] = result[name].crop(crop_width=pad_width)

        return result