Ejemplo n.º 1
0
def make_cube_from_images(flist, outf):
    data = [np.copy(fits.getdata(f, ext=1)) for f in flist]
    shape = np.max(np.array([d.shape for d in data]), axis=0)
    for d in data:
        d.resize(shape)

    cube = Cube(data=np.dstack(data), copy=False)
    cube.write(outf, savemask='nan')
Ejemplo n.º 2
0
 def cont_sub(self, line, z, dv, ddv, savefile=None):
     wv1, wv2, wv3, wv4 = interpWindow(line, z, dv, ddv)
     mask_b = (self.wave >= wv1) & (self.wave <= wv2)
     mask_r = (self.wave >= wv3) & (self.wave <= wv4)
     mask_mid = (self.wave >= (wv1 - 200)) & (self.wave <= (wv4 + 200))
     wavefit = np.concatenate((self.wave[mask_b], self.wave[mask_r]))
     for y in range(0, self.ny):
         for x in range(0, self.nx):
             fluxfit = np.concatenate(
                 (self.data[mask_b, y, x], self.data[mask_r, y, x]))
             z = np.polyfit(wavefit, fluxfit, 1)
             p = np.poly1d(z)
             linemodel = p(self.wave[mask_mid])
             self.data[mask_mid, y, x] -= linemodel
     if savefile is not None:
         cubenew = Cube(data=self.data,
                        var=(self.err)**2,
                        data_header=self.dh,
                        wcs=self.wcs,
                        wave=self.wv)
         cubenew.write(savefile, savemask='none')
Ejemplo n.º 3
0
    def write(self, path=None, erase=False):
        """Save the current session in a folder that will have the name of the
        ORIGIN object (self.name).

        The ORIGIN.load(folder, newname=None) method will be used to load a
        session. The parameter newname will let the user to load a session but
        continue in a new one.

        Parameters
        ----------
        path : str
            Path where the folder (self.name) will be stored.
        erase : bool
            Remove the folder if it exists.

        """
        self._loginfo("Writing...")

        # adapt session if path changes
        if path is not None and path != self.path:
            if not os.path.exists(path):
                raise ValueError(f"path does not exist: {path}")
            self.path = path
            outpath = os.path.join(path, self.name)
            # copy outpath to the new path
            shutil.copytree(self.outpath, outpath)
            self.outpath = outpath
            self._setup_logfile(self.logger)

        if erase:
            shutil.rmtree(self.outpath)
        os.makedirs(self.outpath, exist_ok=True)

        # PSF
        if isinstance(self.PSF, list):
            for i, psf in enumerate(self.PSF):
                cube = Cube(data=psf, mask=np.ma.nomask, copy=False)
                cube.write(os.path.join(self.outpath,
                                        "cube_psf_%02d.fits" % i))
        else:
            cube = Cube(data=self.PSF, mask=np.ma.nomask, copy=False)
            cube.write(os.path.join(self.outpath, "cube_psf.fits"))

        if self.wfields is not None:
            for i, wfield in enumerate(self.wfields):
                im = Image(data=wfield, mask=np.ma.nomask)
                im.write(os.path.join(self.outpath, "wfield_%02d.fits" % i))

        if self.ima_white is not None:
            self.ima_white.write("%s/ima_white.fits" % self.outpath)

        for step in self.steps.values():
            step.dump(self.outpath)

        # parameters in .yaml
        with open(f"{self.outpath}/{self.name}.yaml", "w") as stream:
            dump_yaml(self.param, stream)

        # step3 - saving this manually for now
        if self.nbAreas is not None:
            if self.testO2 is not None:
                for area in range(1, self.nbAreas + 1):
                    np.savetxt("%s/testO2_%d.txt" % (self.outpath, area),
                               self.testO2[area - 1])
            if self.histO2 is not None:
                for area in range(1, self.nbAreas + 1):
                    np.savetxt("%s/histO2_%d.txt" % (self.outpath, area),
                               self.histO2[area - 1])
            if self.binO2 is not None:
                for area in range(1, self.nbAreas + 1):
                    np.savetxt("%s/binO2_%d.txt" % (self.outpath, area),
                               self.binO2[area - 1])

        self._loginfo("Current session saved in %s", self.outpath)
Ejemplo n.º 4
0
		manager = mtp.Manager()
        	return_dict = manager.dict()
	
		tstart = time.time()
		#pool = Pool(processes=20)
		#pool.map(dummy_function, range(c.shape[0]))     
		dummy_im = c[1,:,:].copy()
		dummy_im.data.data[:,:] = 0

		for i in range(0,c.shape[0]):
                	p = Process(target=rm_bg_multiproc, args=(i,c,dummy_im,return_dict))
                        p.start()


		tend = time.time()
                print('ellapsed time %s'%(tend-tstart))

		c.unmask()
		for k in range(c.shape[0]):
			c.data.data[k,:,:] = c.data.data[k,:,:] - return_dict[k]

		## Update Header
        	c.primary_header.add_comment('This cube has been median subtracted')
		c.write(args.cube_out)

	#if args.multip == 0:

	#	remove_bg(args.cube_in,args.mask,args.cube_out)


Ejemplo n.º 5
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.º 6
0
def determine_best_astrometry(magecube_filename, musecube_filename, xypa_tuples,
                              chi2_wvrange, renorm_wvrange, plot_wvrange, plot=True):
    """Utility for determining the best astrometry for a MagE Cube based on a comparisom
    with a reference MUSE Cube. It will use different (xc, yc, PA) positions taken from xypa_tuples
    for a virtual MagE slit on a MUSE reference datacube and will determine the set that
    has the minimum Chi2 within a spectral region. It will return a astropy.table.Table object
    with the results.

    Parameters
    ----------
    magecube : str
        Filename of the MagE cube
    musecube_filename : str
        Filename of the MUSE reference cube
    xyc_tuples: list of tuples
        List of (xc, yc, PA) tuples
        xc and yc are in units of MUSE pixels and
        PA is in the position angle in degrees
    chi2_wvrange : (float, float)
        Wavelength range for performing the chi2 comparison. Ideally it has to be a small
        region centred in a spectral feature (e.g. emission line)
    renorm_wvrange : (float, float)
        Wavelength range for performing the flux renormalization of MagE to MUSE. Ideally it
        has to be a small region close to `chi2_range`.
    plot_wvrange : (float, float)
        Wavelength range for plotting. Must be larger than either renorm_range or chi2_range.
    plot : bool
        Whether to plot the iterations for visual inspection

    Returns
    -------
    results : astropy.table.Table
        Table with the results
    """
    from PyMUSE import musecube as mc
    import os

    # load the cubes
    musecube_pymuse = mc.MuseCube(musecube_filename)
    musecube = Cube(musecube_filename)
    magecube_orig = Cube(magecube_filename)

    # create master subdir
    master_dirname = magecube_filename.split('/')[-1].replace('.fits', '_astrometry_runs')
    if not os.path.exists(master_dirname):
        os.makedirs(master_dirname)

    # define mage slit geometry
    l=0.3*3*11
    w=1.
    n=11
    pixscale = 0.2  # of MUSE datacube

    # create a table to store the results
    tab = Table()

    # will create auxiliary cubes from MUSE to match geometry of mage
    names = []
    if 1:  # left only for the indentantion
        if 1:  # left for the indentation
            for tup in xypa_tuples:
                xc, yc, pac = tup
                rootname = '{:.1f}-{:.1f}-{:.1f}'.format(xc,yc,pac)
                rootname = rootname.replace('.','p')
                names += [rootname]

                if not os.path.exists(master_dirname+'/'+rootname):
                    os.makedirs(master_dirname+'/'+rootname)

                output = master_dirname + '/' + rootname + '/mage_slit_in_muse_{}.reg'.format(rootname)
                ntr.create_regfile_nboxes_from_slit(output, (xc,yc), pac, l, w, n, pixscale)

                # define name
                newcube_name = master_dirname + '/' + rootname + '/magecube_from_muse_{}.fits'.format(rootname)
                # check whether this cube already exists
                if os.path.isfile(newcube_name):
                    print('File already exists, skiping: {}'.format(newcube_name.split('/')[-1]))
                    continue
                else:
                    print('Writing file: {}'.format(newcube_name))
                # create the data structure
                nw, ny, nx = magecube_orig.shape
                nw = musecube.shape[0]  # replace mw with that of muse datacube
                data = np.zeros(shape=(nw, ny, nx))
                var = np.zeros_like(data)

                # get the spectra from MUSE in the given region
                for ii in range(n):
                    plt.figure(musecube_pymuse.n)
                    spec = musecube_pymuse.get_spec_from_ds9regfile(output, mode='sum', i=ii, frac=0.1, npix=0,
                                                          empirical_std=False, n_figure=None,
                                                            save=False, save_mask=False, plot=False)
                    # pymuse gets spectrum in vacuum, thus we will convert to air
                    # because the MUSEcube reduction is in air
                    # does not seem important, but I leave this here for transparency
                    spec.vactoair()
                    data[:, ny-ii-1, 0] = spec.flux
                    var[:, ny-ii-1, 0] = spec.sig**2
                    # import pdb; pdb.set_trace()
                # redefine the structure
                magecube_new = Cube(wcs=magecube_orig.wcs, wave=musecube.wave, data=data, var=var)
                newcube_name = master_dirname + '/' + rootname + '/magecube_from_muse_{}.fits'.format(rootname)
                magecube_new.write(newcube_name)
    # plt.show()
    tab['name'] = names
    tab['xc'] = [float(name.split('-')[0].replace('p','.')) for name in tab['name']]
    tab['yc'] = [float(name.split('-')[1].replace('p','.')) for name in tab['name']]
    tab['PA'] = [float(name.split('-')[2].replace('p','.')) for name in tab['name']]

    # now read the cubes and perform the chi2
    chi2_spec = []
    chi2_flux = []
    fl_mage_11 = []
    fl_muse_11 = []
    for jj, name in enumerate(tab['name']):
        newcube_name = master_dirname + '/' + name + '/magecube_from_muse_{}.fits'.format(name)
        magecube1 = magecube_orig  # MagE original
        magecube2 = Cube(newcube_name)  # from MUSE
        chi2_s, chi2_f, fl_mage, fl_muse = compute_chi2_magecubes(magecube1, magecube2,
                                                    chi2_wvrange=chi2_wvrange,
                                                    renorm_wvrange=renorm_wvrange,
                                                    plot_wvrange=plot_wvrange, plot=plot,
                                                    text1= 'MagE', text2='MUSE')

        print("{}  [{}/{}]".format(name, jj + 1, len(tab)))
        print(" Total Chi2_spec/DOF = {:.1f}".format(chi2_s))
        print(" Total Chi2 flux/DOF = {:.1f}".format(chi2_f))
        chi2_spec += [chi2_s]
        chi2_flux += [chi2_f]
        fl_mage_11 += [fl_mage]
        fl_muse_11 += [fl_muse]
        if plot:
            fig = plt.gcf()
            fig.suptitle(name)

    tab['fl_muse_11'] = fl_muse_11
    tab['fl_mage_11'] = fl_mage_11
    tab['chi2_spec'] = chi2_spec
    tab['chi2_flux'] = chi2_flux
    return tab
Ejemplo n.º 7
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.º 8
0
def determine_best_astrometry(magecube_filename,
                              musecube_filename,
                              xypa_tuples,
                              chi2_wvrange,
                              renorm_wvrange,
                              plot_wvrange,
                              plot=True):
    """Utility for determining the best astrometry for a MagE Cube based on a comparisom
    with a reference MUSE Cube. It will use different (xc, yc, PA) positions taken from xypa_tuples
    for a virtual MagE slit on a MUSE reference datacube and will determine the set that
    has the minimum Chi2 within a spectral region. It will return a astropy.table.Table object
    with the results.

    Parameters
    ----------
    magecube : str
        Filename of the MagE cube
    musecube_filename : str
        Filename of the MUSE reference cube
    xyc_tuples: list of tuples
        List of (xc, yc, PA) tuples
        xc and yc are in units of MUSE pixels and
        PA is in the position angle in degrees
    chi2_wvrange : (float, float)
        Wavelength range for performing the chi2 comparison. Ideally it has to be a small
        region centred in a spectral feature (e.g. emission line)
    renorm_wvrange : (float, float)
        Wavelength range for performing the flux renormalization of MagE to MUSE. Ideally it
        has to be a small region close to `chi2_range`.
    plot_wvrange : (float, float)
        Wavelength range for plotting. Must be larger than either renorm_range or chi2_range.
    plot : bool
        Whether to plot the iterations for visual inspection

    Returns
    -------
    results : astropy.table.Table
        Table with the results
    """
    from PyMUSE import musecube as mc
    import os

    # load the cubes
    musecube_pymuse = mc.MuseCube(musecube_filename)
    musecube = Cube(musecube_filename)
    magecube_orig = Cube(magecube_filename)

    # create master subdir
    master_dirname = magecube_filename.split('/')[-1].replace(
        '.fits', '_astrometry_runs')
    if not os.path.exists(master_dirname):
        os.makedirs(master_dirname)

    # define mage slit geometry
    l = 0.3 * 3 * 11
    w = 1.
    n = 11
    pixscale = 0.2  # of MUSE datacube

    # create a table to store the results
    tab = Table()

    # will create auxiliary cubes from MUSE to match geometry of mage
    names = []
    if 1:  # left only for the indentantion
        if 1:  # left for the indentation
            for tup in xypa_tuples:
                xc, yc, pac = tup
                rootname = '{:.1f}-{:.1f}-{:.1f}'.format(xc, yc, pac)
                rootname = rootname.replace('.', 'p')
                names += [rootname]

                if not os.path.exists(master_dirname + '/' + rootname):
                    os.makedirs(master_dirname + '/' + rootname)

                output = master_dirname + '/' + rootname + '/mage_slit_in_muse_{}.reg'.format(
                    rootname)
                ntr.create_regfile_nboxes_from_slit(output, (xc, yc), pac, l,
                                                    w, n, pixscale)

                # define name
                newcube_name = master_dirname + '/' + rootname + '/magecube_from_muse_{}.fits'.format(
                    rootname)
                # check whether this cube already exists
                if os.path.isfile(newcube_name):
                    print('File already exists, skiping: {}'.format(
                        newcube_name.split('/')[-1]))
                    continue
                else:
                    print('Writing file: {}'.format(newcube_name))
                # create the data structure
                nw, ny, nx = magecube_orig.shape
                nw = musecube.shape[0]  # replace mw with that of muse datacube
                data = np.zeros(shape=(nw, ny, nx))
                var = np.zeros_like(data)

                # get the spectra from MUSE in the given region
                for ii in range(n):
                    plt.figure(musecube_pymuse.n)
                    spec = musecube_pymuse.get_spec_from_ds9regfile(
                        output,
                        mode='sum',
                        i=ii,
                        frac=0.1,
                        npix=0,
                        empirical_std=False,
                        n_figure=None,
                        save=False,
                        save_mask=False,
                        plot=False)
                    # pymuse gets spectrum in vacuum, thus we will convert to air
                    # because the MUSEcube reduction is in air
                    # does not seem important, but I leave this here for transparency
                    spec.vactoair()
                    data[:, ny - ii - 1, 0] = spec.flux
                    var[:, ny - ii - 1, 0] = spec.sig**2
                    # import pdb; pdb.set_trace()
                # redefine the structure
                magecube_new = Cube(wcs=magecube_orig.wcs,
                                    wave=musecube.wave,
                                    data=data,
                                    var=var)
                newcube_name = master_dirname + '/' + rootname + '/magecube_from_muse_{}.fits'.format(
                    rootname)
                magecube_new.write(newcube_name)
    # plt.show()
    tab['name'] = names
    tab['xc'] = [
        float(name.split('-')[0].replace('p', '.')) for name in tab['name']
    ]
    tab['yc'] = [
        float(name.split('-')[1].replace('p', '.')) for name in tab['name']
    ]
    tab['PA'] = [
        float(name.split('-')[2].replace('p', '.')) for name in tab['name']
    ]

    # now read the cubes and perform the chi2
    chi2_spec = []
    chi2_flux = []
    fl_mage_11 = []
    fl_muse_11 = []
    for jj, name in enumerate(tab['name']):
        newcube_name = master_dirname + '/' + name + '/magecube_from_muse_{}.fits'.format(
            name)
        magecube1 = magecube_orig  # MagE original
        magecube2 = Cube(newcube_name)  # from MUSE
        chi2_s, chi2_f, fl_mage, fl_muse = compute_chi2_magecubes(
            magecube1,
            magecube2,
            chi2_wvrange=chi2_wvrange,
            renorm_wvrange=renorm_wvrange,
            plot_wvrange=plot_wvrange,
            plot=plot,
            text1='MagE',
            text2='MUSE')

        print("{}  [{}/{}]".format(name, jj + 1, len(tab)))
        print(" Total Chi2_spec/DOF = {:.1f}".format(chi2_s))
        print(" Total Chi2 flux/DOF = {:.1f}".format(chi2_f))
        chi2_spec += [chi2_s]
        chi2_flux += [chi2_f]
        fl_mage_11 += [fl_mage]
        fl_muse_11 += [fl_muse]
        if plot:
            fig = plt.gcf()
            fig.suptitle(name)

    tab['fl_muse_11'] = fl_muse_11
    tab['fl_mage_11'] = fl_mage_11
    tab['chi2_spec'] = chi2_spec
    tab['chi2_flux'] = chi2_flux
    return tab
Ejemplo n.º 9
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
Ejemplo n.º 10
0
    def create_reference_cube(self,
                              lambdamin=4700,
                              lambdamax=9400,
                              step=1.25,
                              outcube_name=None,
                              filter_for_nan=False,
                              **kwargs):
        """Create a reference cube using an input one, and overiding
        the lambda part, to get a new WCS

        Args:
            lambdamin:
            lambdamax:
            step:
            outcube_name:
            filter_for_nan:
            **kwargs:

        Returns:

        """

        # Separate folder and name of file
        cube_folder, cube_name = os.path.split(self.filename)

        # Creating the outcube filename
        if outcube_name is None:
            prefix = kwargs.pop(
                "prefix", "l{0:4d}l{1:4d}_".format(np.int(lambdamin),
                                                   np.int(lambdamax)))
            outcube_name = "{0}{1}".format(prefix, cube_name)

        # Range of lambd and number of spectral pixels
        range_lambda = lambdamax - lambdamin
        npix_spec = np.int(range_lambda // step + 1.0)

        # if filter_nan remove the Nan
        if filter_for_nan:
            ind = np.indices(self.data[0].shape)
            selgood = np.any(~np.isnan(self.data), axis=0)
            if self._debug:
                upipe.print_debug(
                    "Xmin={0} Xmax={1} / Ymin={2} Ymax={3}".format(
                        np.min(ind[0][selgood]), np.max(ind[0][selgood]),
                        np.min(ind[1][selgood]), np.max(ind[1][selgood])))
            subcube = self[:,
                           np.min(ind[0][selgood]):np.max(ind[0][selgood]),
                           np.min(ind[1][selgood]):np.max(ind[1][selgood])]
        else:
            subcube = self

        # Create the WCS which we need for the output cube
        wcs_header = subcube.get_wcs_header()
        wcs1 = subcube.wcs
        wave1 = WaveCoord(cdelt=step,
                          crval=lambdamin,
                          ctype=wcs_header['CTYPE3'],
                          crpix=1.0,
                          shape=npix_spec)
        # Create a fake dataset with int to be faster
        cube_data = np.ones((npix_spec, wcs1.naxis2, wcs1.naxis1),
                            dtype=np.uint8)
        cube = Cube(data=cube_data, wcs=wcs1, wave=wave1)
        # Write the output
        cube.write(joinpath(cube_folder, outcube_name))

        # just provide the output name by folder+name
        return cube_folder, outcube_name