Ejemplo n.º 1
0
def rotate_cube_wcs(cube_name,
                    cube_folder="",
                    outwcs_folder=None,
                    rotangle=0.,
                    **kwargs):
    """Routine to remove potential Nan around an image and reconstruct
    an optimal WCS reference image. The rotation angle is provided as a way
    to optimise the extent of the output image, removing Nan along X and Y
    at that angle.

    Args:
        cube_name (str): input image name. No default.
        cube_folder (str): input image folder ['']
        outwcs_folder (str): folder where to write the output frame. Default is
            None which means that it will use the folder of the input image.
        rotangle (float): rotation angle in degrees [0]
        **kwargs:
            in_suffix (str): in suffix to remove from name ['prealign']
            out_suffix (str): out suffix to add to name ['rotwcs']
            margin_factor (float): factor to extend the image [1.1]

    Returns:

    """

    # Reading the input names and setting output folder
    fullname = joinpath(cube_folder, cube_name)
    cube_folder, cube_name = os.path.split(fullname)
    if outwcs_folder is None:
        outwcs_folder = cube_folder

    # Suffix
    in_suffix = kwargs.pop("in_suffix", "prealign")
    out_suffix = kwargs.pop("out_suffix", "rotwcs")

    # Get margin if needed
    margin_factor = kwargs.pop("margin_factor", 1.1)
    extend_fraction = np.maximum(0., (margin_factor - 1.))
    upipe.print_info("Will use a {:5.2f}% extra margin".format(
        extend_fraction * 100.))

    # Opening the image via mpdaf
    cubewcs = Cube(fullname)
    imawcs = cubewcs.sum(axis=0)
    extra_pixels = (np.array(imawcs.shape) * extend_fraction).astype(np.int)

    # New dimensions and extend current image
    new_dim = tuple(np.array(imawcs.shape).astype(np.int) + extra_pixels)
    ima_ext = imawcs.regrid(newdim=new_dim,
                            refpos=imawcs.get_start(),
                            refpix=tuple(extra_pixels / 2.),
                            newinc=imawcs.get_step()[0] * 3600.)

    # Copy and rotate WCS
    new_wcs = copy.deepcopy(ima_ext.wcs)
    upipe.print_info(
        "Rotating spatial WCS of Cube by {} degrees".format(rotangle))
    new_wcs.rotate(rotangle)

    # New rotated image
    ima_rot = Image(data=np.nan_to_num(ima_ext.data), wcs=new_wcs)

    # Then resample the image using the initial one as your reference
    ima_rot_resampled = ima_rot.align_with_image(ima_ext, flux=True)

    # Crop NaN
    ima_rot_resampled.crop()

    # get the new header with wcs and rotate back
    finalwcs = ima_rot_resampled.wcs
    finalwcs.rotate(-rotangle)

    # create the final image
    data_cube_rot = np.repeat(ima_rot_resampled[np.newaxis, :, :].data,
                              cubewcs.shape[0],
                              axis=0)
    final_rot_cube = Cube(data=data_cube_rot, wave=cubewcs.wave, wcs=finalwcs)

    # Save image
    if isinstance(in_suffix,
                  str) and in_suffix != "" and in_suffix in cube_name:
        out_name = cube_name.replace(in_suffix, out_suffix)
    else:
        name, extension = os.path.splitext(cube_name)
        if out_suffix != "":
            out_suffix = "_{}".format(out_suffix)
        out_name = "{0}{1}{2}".format(name, out_suffix, extension)

    # write output
    final_rot_cube.write(joinpath(outwcs_folder, out_name))
    return outwcs_folder, out_name
Ejemplo n.º 2
0
class check_musepipe(object): 
    """Graphic output to check MUSE data reduction products
    """
    
    def __init__(self, cube_folder='./', cube_name=None, verbose=False) :
        """
        """
        self.verbose = verbose
        self.cube_folder = cube_folder
        self.cube_name = cube_name

        # Open the cube and extract spectra if cube name is given
        self.open_cube(cube_folder, cube_name)
        if self._isCube :
            self.get_set_spectra()
            self.get_set_images()

    def open_cube(self, cube_folder=None, cube_name=None) :
        """Open the cube
        """
        # Check if cube folder and name are given 
        if cube_folder is not None : 
            self.cube_folder = cube_folder
        if cube_name is not None : 
            self.cube_name = cube_name

        # Check if cube exists
        if (self.cube_folder is None) | (self.cube_name is None) :
            self._isCube = False
            print("WARNING: No appropriate Cube name and folder defined")
            return

        cubepath = joinpath(self.cube_folder, self.cube_name)
        if os.path.isfile(cubepath) :
            self._isCube = True
            self.cube_galaxy = Cube(cubepath)
        else :
            self._isCube = False
            print("WARNING: Cube {0} not found".format(cubepath))

    def open_image(self, image_folder="./", image_name=None) :
        """Open the image
        """
        self.image_folder = image_folder
        self._isImage = True
        self.image_name = image_name
        if (imagein is None) | (not os.path.isfile(joinpath(image_folder, imagein))):
            self._isImage = False
        else :
            self._isImage = True
        self.image_galaxy = Image(joinpath(image_folder, image_name))

    def get_spectrum_from_cube(self, nx=None, ny=None, width=0) :
        if not self._isCube : 
            print("WARNING: No Cube is defined, yet")
            return

        if nx == None : nx = self.cube_galaxy.shape[2] // 2
        if ny == None : ny = self.cube_galaxy.shape[1] // 2
        width2 = width // 2
        return (self.cube_galaxy[:, ny - width2: ny + width2 + 1, 
                    nx - width2: nx + width2 + 1]).sum(axis=(1,2))

    def get_image_from_cube(self, nlambda=None, width=0) :
        if not self._isCube : 
            print("WARNING: No Cube is defined, yet")
            return

        if nlambda == None : nlambda = self.cube_galaxy.shape[0] // 2
        width2 = width // 2
        return (self.cube_galaxy[nlambda - width2: nlambda + width2 + 1, :, :].sum(axis=0))

    def get_set_images(self) :
        """Get a set of standard images from the Cube
        """
        pass

    def get_set_spectra(self) :
        """Get a set of standard spectra from the Cube
        """
        if self._isCube :
            self.spec_fullgalaxy = self.cube_galaxy.sum(axis=(1,2))
            self.spec_4quad = self.get_quadrant_spectra_from_cube()
            self.spec_central_aper = [self.get_spectrum_from_cube(width=0), 
                   self.get_spectrum_from_cube(width=20), self.get_spectrum_from_cube(width=40)]

    def get_quadrant_spectra_from_cube(self, width=0) :
        """Get quadrant spectra from the Cube

        Input
        ----
        width : width of integration
        """
        if not self._isCube : 
            print("WARNING: No Cube is defined, yet")
            return

        ny4 = self.cube_galaxy.shape[1] // 4
        nx4 = self.cube_galaxy.shape[2] // 4
        nx34, ny34 = 3 * nx4, 3 * ny4

        spec1 = self.get_spectrum_from_cube( nx4,  ny4, width) 
        spec2 = self.get_spectrum_from_cube( nx4, ny34, width) 
        spec3 = self.get_spectrum_from_cube(nx34,  ny4, width) 
        spec4 = self.get_spectrum_from_cube(nx34, ny34, width) 
        return spec1, spec2, spec3, spec4

    def check_bias(self) :
        pass
        # bias = RawFile(self. ..)

    def check_flat(self) :
        pass

    def check_finalcube(self) :
        pass
Ejemplo n.º 3
0
	f = open('psf_results.dat','w')
	f.write('Wavelengh (A)	Gaussian FWHM (")	Moffat n/beta (") 	Moffat fwhm (") 	Moffat alpha(")\n')
	f.write('--------------------------------------------------------------------------------------------------------\n')

	## Read star list and open output results
        id,ra,dec = np.loadtxt(args.star_list,unpack=True)
	
	## Load cube and bin 
	c = Cube(args.cube)
	c = c.rebin((2*368,1,1))
	sample_fwhm = []
	sample_gfwhm= []
	sample_n = []
	sample_alpha = []
	white = c.sum(axis=0)
	(gfwhm,std_gfwhm,fwhm,std_fwhm,n,std_n) = measure_psf(white,ra,dec)
	alpha = fwhm / (2 *np.sqrt(2 * (1/n) - 1))
        err_alpha = std_fwhm / (2 *np.sqrt(2 * (1/n) - 1)) + std_n * fwhm / (2 * np.sqrt(2/n- n*n))
                        ## ugly derivative with Wolfram Alpha
	f.write('white light \t %0.2f +/- %0.2f \t %0.2f +/- %0.2f \t %0.2f +/- %0.2f \t %0.2f +/- %0.2f \n'
                        %(gfwhm,std_gfwhm,n,std_n,fwhm,std_fwhm, alpha,err_alpha))
	f.write('--------------------------------------------------------------------------------------------------------\n')
		
	for k in range(0,c.shape[0]):
		print('Measusing %s out of 5 slices'%k)
		im = c[k]
		im.wcs = c.wcs ## Not elegant, but the wcs is not keept when you only select one slice
		(gfwhm,std_gfwhm,fwhm,std_fwhm,n,std_n) = measure_psf(im,ra,dec)
		
		## Convert mpdaf fwhm in proper moffat parameters
Ejemplo n.º 4
0
def make_MagE_cube_v2(config_file, format='txt'):
    """A new version to create the MagE cubes, it uses MPDAF objects.
    It works for .fits 1-d spectra files stored in a directory with a specific
    format. In particular:

    XXX_yyy_??.txt

    Errors are looked for in the same directory with *_sig.fits extension


    Parameters
    ----------
    config_file : str
        Configuration file with important parameters. See mage.dump_config_make_MagE_cube()
    format : str
        Either 'fits' of 'txt'

    Returns:
        Cube fits files associated to each "XX_yyy"

    """

    # read config_filename and add filename to params
    f = open(config_file)
    params = json.load(f)
    params['config_filename'] = config_file

    # reference files
    reference_mage_file = params['reference_mage']
    reference_muse_file = params['reference_muse']

    # Add comment on how the header was created
    comment = 'Cube created by pyntejos.mage.make_MagE_cube.py based on headers from {} and {}. Astrometry ' \
              'and wavelength axis given by input configuration ' \
              'file {}.'.format(reference_mage_file.split('/')[-1],reference_muse_file.split('/')[-1], params['config_filename'])

    # Print message
    print('')
    print(comment.replace("Cube created", "MagE cube will be created"))

    dirname = params['directory_mage']
    # filenames = glob.glob(dirname+"/*syn_??.fits")
    if format == 'txt':
        rootname = params["rootname"]
        print('rootname: '+rootname)
        filenames = glob.glob(dirname+"/{}_??.txt".format(rootname))
        # print(filenames)
    elif format == 'fits':
        raise NotImplementedError("Not properly implemented. It's almost there but depends on the file structures.")
    if len(filenames) == 0:
        raise ValueError("No files found matching the rootname: {}".format(rootname))

    # sort them
    filenames.sort()

    # create the new datacube structure
    # spec_ref = readspec(filenames[0])
    nw, ny, nx = params['NAXIS3'], params['NAXIS2'], params['NAXIS1']

    # get wavecoord
    # hdr = spec_ref.header
    # hdr['CUNIT1'] = 'Angstrom'
    crpix = params['CRPIX3']
    cdelt = params['CD3_3']
    crval = params['CRVAL3']
    wave = WaveCoord(hdr=None, crpix=crpix, cdelt=cdelt, crval=crval, cunit=u.AA, ctype='LINEAR', shape=None)
    # wave = WaveCoord(hdr=hdr)
    # get WCS
    crpix_yx = params['CRPIX2'], params['CRPIX1']  # note y,x order
    crval_decra = params['CRVAL2'], params['CRVAL1']  # ditto
    cdelt_yx = params['PIXSCALE_Y'], -1*params['PIXSCALE_X']  # ditto (negative to decrease towards east)
    PA = params['POS_ANGLE']
    if PA == "None": # get angle from MagE reference header
        print("No PA given in parameter file. Reding PA from MagE reference .fits header")
        hdulist_mage = fits.open(params['reference_mage'])
        PA = hdulist_mage[0].header['ROTANGLE'] - 44.5  # this is the current offset in angle
        print("PA={}deg".format(PA))
    shape = (ny, nx)
    wcs = WCS(crpix=crpix_yx, crval=crval_decra, cdelt=cdelt_yx, deg=True, shape=shape, rot=-1*PA)  # for some reason negative PA works
    # redefine wcs to have CD matrix rather than PC matrix
    if 1: #rot != 0:
        hdr = wcs.to_header()
        hdr.rename_keyword('PC1_1','CD1_1')
        hdr.rename_keyword('PC2_1','CD2_1')
        hdr.rename_keyword('PC1_2','CD1_2')
        hdr.rename_keyword('PC2_2','CD2_2')
        # hdr['CD1_1'] = hdr['PC1_1']
        # hdr['CD2_1'] = hdr['PC2_1']
        # hdr['CD1_2'] = hdr['PC1_2']
        # hdr['CD2_2'] = hdr['PC2_2']
        wcs = WCS(hdr=hdr)

    # create data structures
    data = np.zeros_like(np.ndarray(shape=(nw,ny,nx)))
    var = np.zeros_like(data)

    # read the files and fill the data cubes (cube and variance)
    print("Reading files from directory {} ordered as:".format(dirname))
    for ii,fname in enumerate(filenames):
        fn = fname.split('/')[-1]
        yspaxel = ny - ii  # larger y will be the northern one
        print("\t {}: {} --goes to--> spaxel (1,{})".format(ii + 1, fn, yspaxel))
        # MAKE SURE THE SPECTRA IS PROPERLY SORTED
        nfile = fn.split('.')[0].split('_')[-1]
        nfile = int(nfile)
        assert nfile == ii + 1, "The files in the directory are not sorted properly. Please check."

        if format=='fits':
            try:
                spec = readspec(fname)
                if 0: # dummy
                    spec.flux = 1
                    spec.sig = 0
                data[:,yspaxel-1,0] = spec.flux.value  # position "01" is the most north, y increase to north
                if np.isnan(spec.sig):
                    try:
                        spec_sig = readspec(fname.replace('flux','sigm'))
                        spec.sig = spec_sig.flux.value
                    except:
                        spec.sig = 0
                var[:,yspaxel-1,0] = (spec.sig.value)**2
            except:
                print("Something is wrong with spectrum {}".format(fname.split('/')[-1]))
                import pdb; pdb.set_trace()
                raise ValueError("Something is wrong with spectrum {}".format(fname.split('/')[-1]))
        elif format=='txt':
            spec = read_single_mage_file(fname)
            data[:, yspaxel - 1, 0] = spec.flux
            var[:, yspaxel - 1, 0] = (spec.sig)**2
            # import pdb;pdb.set_trace()

    # create the Cube object
    cube = Cube(data=data, var=var, wcs=wcs, wave=wave)
    outputname = '{}_cube_{}.fits'.format(params['rootname'], params['datestamp'])
    cube.write(outputname)
    print('Wrote file: {}'.format(outputname))

    # create white image
    white = cube.sum(axis=0)
    white.write(outputname.replace('cube', 'white'))
    print('Wrote file: {}'.format(outputname.replace('cube', 'white')))
    # import pdb; pdb.set_trace()
    return cube
Ejemplo n.º 5
0
def make_MagE_cube_v2(config_file, format='txt'):
    """A new version to create the MagE cubes, it uses MPDAF objects.
    It works for .fits 1-d spectra files stored in a directory with a specific
    format. In particular:

    XXX_yyy_??.txt
        Where XXX -> Name of object
        yyy -> ['flx', 'nor', syn']
        ?? -> ['01', '02', ..., '11']

    Each individual file must contain its error array


    Parameters
    ----------
    config_file : str
        Configuration file with important parameters. See mage.dump_config_make_MagE_cube()
        for an example
    format : str
        Only '.txt' format is allowed. The convention is set by N.Tejos and S.Lopez
    northernmost_ypixel : str
        What is the Northernmost spaxel, either '11' or '1'

    Returns:
        Cube fits files associated to each "XX_yyy" object
        It writes the .fits to disk

    """

    # read config_filename and add filename to params
    f = open(config_file)
    params = json.load(f)
    params['config_filename'] = config_file

    # reference files
    reference_mage_file = params['reference_mage']
    reference_muse_file = params['reference_muse']

    # Add comment on how the header was created
    comment = 'Cube created by pyntejos.mage.make_MagE_cube.py based on headers from {} and {}. Astrometry ' \
              'and wavelength axis given by input configuration ' \
              'file {}.'.format(reference_mage_file.split('/')[-1],reference_muse_file.split('/')[-1], params['config_filename'])

    # Print message
    print('')
    print(comment.replace("Cube created", "MagE cube will be created"))

    dirname = params['directory_mage']
    rootname = params['rootname']
    # filenames = glob.glob(dirname+"/*syn_??.fits")
    print('rootname: ' + rootname)
    if format == 'txt':
        # import pdb; pdb.set_trace()
        filenames = glob.glob(dirname + "/{}_??.txt".format(rootname))
        print('This format is deprecated. Please use .fits instead.')
        # print(filenames)

    #elif format == 'fits':
    #    filenames = glob.glob(dirname + "/{}_flux_??.fits".format(rootname))

    else:
        #raise ValueError('Only implemented for .txt or .fits files.')
        raise ValueError(
            'Only implemented for .txt files (with a special format convention).'
        )

    if len(filenames) == 0:
        raise ValueError(
            "No files found matching the rootname: {}".format(rootname))

    # sort them
    filenames.sort()

    # the structure must be consistent with that specified by the user in the config file
    nw, ny, nx = params['NAXIS3'], params['NAXIS2'], params['NAXIS1']

    # get wavecoord
    # hdr = spec_ref.header
    # hdr['CUNIT1'] = 'Angstrom'

    crpix = params['CRPIX3']
    cdelt = params['CDELT3']
    crval = params['CRVAL3']
    wave = WaveCoord(hdr=None,
                     crpix=crpix,
                     cdelt=cdelt,
                     crval=crval,
                     cunit=u.AA,
                     ctype='LINEAR',
                     shape=None)
    # wave = WaveCoord(hdr=hdr)
    # get WCS
    crpix_yx = params['CRPIX2'], params['CRPIX1']  # note y,x order
    crval_decra = params['CRVAL2'], params['CRVAL1']  # ditto
    cdelt_yx = params['PIXSCALE_Y'], -1 * params[
        'PIXSCALE_X']  # ditto (negative to decrease towards east)
    PA = params['POS_ANGLE']
    if PA == "None":  # get angle from MagE reference header
        print(
            "No PA given in parameter file. Reading PA from MagE reference .fits header"
        )
        hdulist_mage = fits.open(params['reference_mage'])
        PA = hdulist_mage[0].header[
            'ROTANGLE'] - 44.5  # this is the current offset in angle
        print("\tPA={}deg".format(PA))

    shape = (ny, nx)
    wcs = WCS(crpix=crpix_yx,
              crval=crval_decra,
              cdelt=cdelt_yx,
              deg=True,
              shape=shape,
              rot=-1 * PA)  # for some reason negative PA works
    # redefine wcs to have CD matrix rather than PC matrix
    if 1:  #rot != 0:
        hdr = wcs.to_header()
        hdr.rename_keyword('PC1_1', 'CD1_1')
        hdr.rename_keyword('PC2_1', 'CD2_1')
        hdr.rename_keyword('PC1_2', 'CD1_2')
        hdr.rename_keyword('PC2_2', 'CD2_2')
        # hdr['CD1_1'] = hdr['PC1_1']
        # hdr['CD2_1'] = hdr['PC2_1']
        # hdr['CD1_2'] = hdr['PC1_2']
        # hdr['CD2_2'] = hdr['PC2_2']
        wcs = WCS(hdr=hdr)

    # create data structures
    data = np.zeros_like(np.ndarray(shape=(nw, ny, nx)))
    var = np.zeros_like(data)

    # read the files and fill the data cubes (cube and variance)
    print("Reading files from directory {} ordered as:".format(dirname))
    print('Northernmost position is {}'.format(
        params['northernmost_position']))
    for ii, fname in enumerate(filenames):
        fn = fname.split('/')[-1]
        if params['northernmost_position'] == '11':
            yspaxel = ny - ii  # larger y will be the northern one
        elif params['northernmost_position'] == '01':
            yspaxel = ii + 1
        else:
            raise ValueError(
                '`northernmost_position` must be either `11` or `01` (str) in the configuration file.'
            )

        print("\t {}: {} --goes to--> spaxel (1,{}) ; i.e. y_python={}".format(
            ii + 1, fn, yspaxel, yspaxel - 1))
        # MAKE SURE THE SPECTRA IS PROPERLY SORTED
        nfile = fn.split('.')[0].split('_')[-1]
        nfile = int(nfile)
        assert nfile == ii + 1, "The files in the directory are not sorted properly. Please check."
        '''
        if format=='fits':
            spec = readspec(fname)
            if 0:  # dummy
                spec.flux = 1
                spec.sig = 0

            if spec.sig_is_set:
                flux_aux = spec.flux.value
                sigm_aux = spec.sig.value
            else:  # get the sigma values from another file
                try:
                    # import pdb; pdb.set_trace()
                    sigma_file = fname.replace('flux', 'sigm')
                    spec_sig = readspec(sigma_file)
                    spec.sig = spec_sig.flux
                except:
                    print("No sigma spectrum was found in the directory with the right name: {}".format(sigma_file))
                    spec.sig = 0
                flux_aux = spec.flux.value
                sigm_aux = spec.sig.value

            data[:, yspaxel-1, 0] = flux_aux
            var[:, yspaxel-1, 0] = (sigm_aux) ** 2
            print("Reading {}, storing it into y={}".format(fname, yspaxel-1))
        '''

        if format == 'txt':
            spec = read_single_mage_file(fname)
            data[:, yspaxel - 1, 0] = spec.flux
            var[:, yspaxel - 1, 0] = (spec.sig)**2
            # import pdb;pdb.set_trace()

    # create the Cube object
    cube = Cube(data=data, var=var, wcs=wcs, wave=wave)
    outputname = '{}_cube_{}.fits'.format(params['rootname'],
                                          params['datestamp'])
    cube.write(outputname)
    print('Wrote file: {}'.format(outputname))

    # create white image
    white = cube.sum(axis=0)
    white.write(outputname.replace('cube', 'white'))
    print('Wrote file: {}'.format(outputname.replace('cube', 'white')))
    # import pdb; pdb.set_trace()
    return cube