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')
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')
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)
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)
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
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
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
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
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
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