def match_higal_to_cohrs(output='HIGAL_MATCHED',search='70to500'): higaldict, codict = inventory(search=search) for cofile in codict: matching = identify_higal_overlaps(cofile, COFootprint=codict, HigalFootprint = higaldict) if matching: subprocess.call('rm -rf montagetmp tmp.fits '+ 'montage_output '+ 'template_header.hdr',shell=True) os.mkdir('montagetmp') for thisfile in matching: os.symlink(datadir+'/HIGAL/'+thisfile,'montagetmp/'+thisfile) hdu = fits.open(datadir+'COHRS/'+cofile,memmap=False) w = wcs.WCS(hdu[0].header) hdr2 = w.to_header() hdr2['BMAJ'] = 15./3600 hdr2['BMIN'] = 15./3600 hdr2['BPA'] = 0. s = SpectralCube(hdu[0].data,w,header=hdr2) thisslice = s[0,:,:] thisslice.write('tmp.fits') hdr = fits.getheader('tmp.fits') hdr.totextfile('template_header.hdr') montage.mosaic('montagetmp','montage_output', header='template_header.hdr',exact_size=True) new_higal_name = cofile.replace('cohrs','higal_xmatch') os.rename('montage_output/mosaic.fits', datadir+output+'/'+new_higal_name) subprocess.call('rm -rf montagetmp tmp.fits '+ 'montage_output '+ 'template_header.hdr',shell=True)
def toMosaic(self, outfile): """ Creates a single FITS file from each detector, and then uses Montage to create a mosaic of all of the said files. """ if len(self.detectors) > 1: import montage_wrapper as montage self._log("info", "Converting to FITS mosaic") tmp_dir = os.path.join(self.out_path, "tmp-" + str(uuid.uuid4())) os.makedirs(tmp_dir) tmp_out_dir = os.path.join(self.out_path, "tmp-out-" + str(uuid.uuid4())) tmp_work_dir = os.path.join(self.out_path, "tmp-work-" + str(uuid.uuid4())) self.toFits(os.path.join(tmp_dir, "image.fits")) montage.mosaic(tmp_dir, tmp_out_dir, background_match=True, work_dir=tmp_work_dir) self._log("info", "Mosaic finished running") shutil.copy(os.path.join(tmp_out_dir, "mosaic.fits"), outfile) if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir) if os.path.exists(tmp_out_dir): shutil.rmtree(tmp_out_dir) if os.path.exists(tmp_work_dir): shutil.rmtree(tmp_work_dir) self._log("info", "Created FITS file %s and cleaned up" % (outfile)) return [outfile] else: self._log("info", "Not creating single-detector mosaic") return []
def coadd_mosaic(filenames=[], as_string=False, match=True, clean=False): indir = tempfile.mkdtemp('_mosaic_in') outdir = tempfile.mkdtemp('_mosaic_out') out = None id = 0 for file in filenames: # Make filenames more unique newname = posixpath.split(file)[-1] newname = '%d_%s' % (id, newname) newname = posixpath.join(indir, newname) print "Matching file %s" % file command = "./crop" if match: command = command + " -match" if clean: command = command + " -clean" os.system("%s %s %s" % (command, file, newname)) #blind_match(file, outname=newname) id = id + 1 print "Running Montage" # Montage will re-create the dir shutil.rmtree(outdir, ignore_errors=True) montage.mosaic(indir, outdir) mosaic_name = posixpath.join(outdir, 'mosaic.fits') if posixpath.exists(mosaic_name): if as_string: with open(mosaic_name, 'r') as file: out = file.read() else: fd, outname = tempfile.mkstemp(prefix='mosaic_', suffix='.fits') os.close(fd) shutil.copy(mosaic_name, outname) out = outname shutil.rmtree(indir, ignore_errors=True) shutil.rmtree(outdir, ignore_errors=True) print "Mosaicking finished" return out
def mosaics(input_list, name, path=None): ''' This module is intended to create mosaics of specified lines/elements. linemaps should have been created beforehand using the ``linemaps`` module Args: input_list : :obj:`list` The list of specific linemaps to be used to mosaic name : :obj:`str` Name of the created mosaic Kwargs: path: :obj:`str` (optional, default: current directory) I/O path ''' if path == None: path = os.getcwd() if os.path.exists(path + '/temp/') == False: os.mkdir(path + '/temp/') if os.path.exists(path + '/mosaics/') == False: os.mkdir(path + '/mosaics/') for idx, f in enumerate(input_list): shutil.copy(f, path + '/temp/' + str(idx) + '.fits') montage.mosaic(path + '/temp/', path + '/mosaic_temp/',\ background_match=True, exact_size=True, cleanup=True) shutil.copy(path + '/mosaic_temp/mosaic_area.fits',\ path + '/mosaics/exp_' + name + '.fits') shutil.copy(path + '/mosaic_temp/mosaic.fits',\ path + '/mosaics/' + name + '.fits') shutil.rmtree(path + '/mosaic_temp/') shutil.rmtree(path + '/temp/')
def cubesplit(): # Change this to match the pattern of whatever cubes you have. flist = glob.glob(cubedir + 'grs-*-cube.fits') spaxis = np.linspace(-30, 160, 191) * u.km / u.s for thisfile in flist: s = SpectralCube.read(thisfile, hdu=0) # If the cubes aren't on a common spectral axis, reproject. s2 = s.spectral_interpolate(spaxis, fill_value=np.nan) shapevec = s2.shape for i in np.arange(shapevec[0]): plane = s2[i, :, :] vel = spaxis[i].value root = thisfile.split('/')[-1] # import pdb; pdb.set_trace() plane.write(splitdir + root.replace( '.fits', '_{0}.fits'.format(vel)), overwrite=True) def planemontage(): # hdr = fits.getheader('INTEG/COHRS_RELEASE1_FULL_INTEG.fit') # try: # hdr.tofile('template.hdr') # except: # pass spaxis = np.linspace(-30, 160, 191) * u.km / u.s for v in spaxis: flist = glob.glob(splitdir + '*cube_{0}.fit*'.format(v.value)) shutil.rmtree(workdir, True) shutil.rmtree(outdir, True) os.mkdir(workdir) for thisfile in flist: shutil.copy(thisfile, workdir) montage.mosaic(workdir,outdir,header='template.hdr', mpi=True, n_proc=8, exact_size=True) os.rename(outdir + 'mosaic.fits', planesdir + 'GRSPLANE_{0}'.format(v.value)+'.fits') shutil.rmtree(outdir, True)
def worker(f): print("PID: %d \t Cluster: %s" % (os.getpid(), f)) os.chdir(f) for band in 'ugriz': if not os.path.isdir(band): os.mkdir(band) images = glob('*_{}_*.fits'.format(band)) for i in images: os.rename('./{}'.format(str(i)), './{}/{}'.format(band, str(i))) # make the mosaics try: montage.mosaic(band, '{}_mosaic'.format(band), background_match=True, combine='median', work_dir='./{}_tmp'.format(band)) except OSError as e: # montage throws an error if any directory already exists. Check all # directories to make sure we haven't missed anything. error(traceback.format_exc()) continue return f
def get_montage_cutout(frame_data, ra, dec, size, mosaic_directory='tmp__mosaic'): centre_pos = SkyCoord(ra, dec, unit=u.degree, frame='fk5') dx = 4 * float(size) * u.arcsec dy = 4 * float(size) * u.arcsec try: shutil.rmtree(mosaic_directory) except FileNotFoundError: pass with tempfile.TemporaryDirectory() as tmp_fits_dir: # write fits data to temporary files for montage [ [ fits.append( os.path.join(tmp_fits_dir, 'out_{}.fits'.format(i)), hdu.data, hdu.header ) for hdu in fd['fits'] ] for i, fd in enumerate(frame_data['r']) ] # perform the mosaic montage.mosaic(tmp_fits_dir, mosaic_directory, background_match=True) # make a cutout of the desired region montage_wcs = WCS(os.path.join(mosaic_directory, 'mosaic.fits')) with fits.open(os.path.join(mosaic_directory, 'mosaic.fits')) as montage_result: cutout = Cutout2D( montage_result[0].data, centre_pos, (dx, dy), wcs=montage_wcs, mode='partial', copy=True, ) return cutout
def montageDir(inputDir, outputDir): return montage.mosaic(inputDir, outputDir, background_match=True)
cluster_r[:, :, i] = fits.getdata(dir + '/Data_r/Cluster_r_reduced/Cluster_r_0' + str(i) + '.fits') cluster_v = np.zeros((1024, 1024, 25)) for i in range(0, 25): cluster_v[:, :, i] = fits.getdata(dir + '/Data_v/Cluster_v_reduced/Cluster_v_0' + str(i) + '.fits') cluster_b = np.zeros((1024, 1024, 25)) for i in range(0, 25): cluster_b[:, :, i] = fits.getdata(dir + '/Data_b/Cluster_b_reduced/Cluster_b_0' + str(i) + '.fits') """ #input and output directories, B-filter; input_dir_B = dir + '/Data_b' output_dir_B = dir + '/mosaic_B' montage.mosaic(input_dir_B, output_dir_B, background_match=True, combine='median') #R-filter input_dir_R = dir + '/Data_r' output_dir_R = dir + '/mosaic_R' montage.mosaic(input_dir_R, output_dir_R, background_match=True, combine='median') #V-filter input_dir_V = dir + '/Data_v' output_dir_V = dir + '/mosaic_V' montage.mosaic(input_dir_V, output_dir_V, background_match=True, combine='median') """
def main(arguments = None): """ main() function, encapsulated in a method to allow for easy invokation. This method follows Guido van Rossum's suggestions on how to write Python main() functions in order to make them more flexible. By encapsulating the main code of the script in a function and making it take an optional argument the script can be called not only from other modules, but also from the interactive Python prompt. Guido van van Rossum - Python main() functions: http://www.artima.com/weblogs/viewpost.jsp?thread=4829 Keyword arguments: arguments - the list of command line arguments passed to the script. """ if arguments is None: arguments = sys.argv[1:] # ignore argv[0], the script name (options, args) = parser.parse_args(args = arguments) # Print the help and abort the execution if there are fewer than three # positional arguments left, as the user must specify at least two FITS # images and the output mosaic into which they are assembled. if len(args) < 3: parser.print_help() return 2 # used for command line syntax errors else: assert len(args) >= 3 input_paths = set(args[:-1]) output_path = args[-1] # Refuse to overwrite the output FITS file unless explicitly instructed to # do so. Note that, if the --overwritten option is given, we do not need to # delete the existing file: it will be silently overwritten when the output # of montage.mosaic() is shutil.move()'d to the output path. if os.path.exists(output_path): if not options.overwrite: msg = "%sError. The output file '%s' already exists." print msg % (style.prefix, output_path) print style.error_exit_message return 1 # Workaround for a bug in montage.mosaic() that raises an error ('mpirun # has exited due to process rank [...] without calling "finalize"...') if # mpi = True and background_match = True. Until this is fixed, we can only # use one core if the --background-match option is given by the user. if options.background_match and options.ncores > 1: options.ncores = 1 for msg in ( "{0}Warning: --background-match is incompatible with --cores > 1.", "{0}Setting the --cores option to a value of one.", "{0}This is a workaround for a known bug in montage-wrapper:", "{0}https://github.com/astropy/montage-wrapper/issues/18"): print msg.format(style.prefix) print # Map each filter to a list of FITSImage objects files = fitsimage.InputFITSFiles() msg = "%sMaking sure the %d input paths are FITS images..." print msg % (style.prefix, len(input_paths)) methods.show_progress(0.0) for index, path in enumerate(input_paths): # fitsimage.FITSImage.__init__() raises fitsimage.NonStandardFITS if # one of the paths is not a standard-conforming FITS file. try: img = fitsimage.FITSImage(path) # If we do not need to know the photometric filter (because the # --filter was not given) do not read it from the FITS header. # Instead, use None. This means that 'files', a dictionary, will # only have a key, None, mapping to all the input FITS images. if options.filter: pfilter = img.pfilter(options.filterk) else: pfilter = None files[pfilter].append(img) except fitsimage.NonStandardFITS: print msg = "'%s' is not a standard FITS file" raise fitsimage.NonStandardFITS(msg % path) percentage = (index + 1) / len(input_paths) * 100 methods.show_progress(percentage) print # progress bar doesn't include newline # The --filter option allows the user to specify which FITS files, among # all those received as input, must be combined: only those images taken # in the options.filter photometric filter. if options.filter: msg = "%s%d different photometric filters were detected:" print msg % (style.prefix, len(files.keys())) for pfilter, images in sorted(files.iteritems()): msg = "%s %s: %d files (%.2f %%)" percentage = len(images) / len(files) * 100 print msg % (style.prefix, pfilter, len(images), percentage) msg = "%sIgnoring images not taken in the '%s' photometric filter..." print msg % (style.prefix, options.filter) , sys.stdout.flush() discarded = 0 for pfilter, images in files.items(): if pfilter != options.filter: discarded += len(images) del files[pfilter] if not files: print msg = "%sError. No image was taken in the '%s' filter." print msg % (style.prefix, options.filter) print style.error_exit_message return 1 else: print 'done.' msg = "%s%d images taken in the '%s' filter, %d were discarded." print msg % (style.prefix, len(files), options.filter, discarded) # montage.mosaic() silently ignores those FITS images that have no WCS # information in their headers, and also raises a rather cryptic exception # (mMakeHdr: Invalid table file) if none of them has been astrometrically # solved. Instead of ignoring some images without warning or showing a # confusing error message that makes it almost impossible to understand # what may be failing, use FITSImage.center_wcs() to make sure that all the # images have WCS information, raising NoWCSInformationError otherwise. for img in files: # May raise NoWCSInformationError img.center_wcs() # montage.mosaic() requires as first argument the directory containing the # input FITS images but, in order to maintain the same syntax across all # LEMON commands, we receive them as command-line arguments. Thus, create a # temporary directory and symlink from it the input images. Hard links are # not an option because os.link() will raise "OSError: [Errno 18] Invalid # cross-device link" if the temporary directory is created in a different # partition. pid = os.getpid() suffix = "_LEMON_%d_mosaic" % pid kwargs = dict(suffix = suffix + '_input') input_dir = tempfile.mkdtemp(**kwargs) atexit.register(methods.clean_tmp_files, input_dir) for img in files: path = img.path source = os.path.abspath(path) basename = os.path.basename(path) link_name = os.path.join(input_dir, basename) os.symlink(source, link_name) # The output of montage.mosaic() is another directory, to which several # files are written, so we need the path to a second temporary directory. # Delete it before calling mosaic(), as otherwise it will raise IOError # ("Output directory already exists"). kwargs = dict(suffix = suffix + '_output') output_dir = tempfile.mkdtemp(**kwargs) atexit.register(methods.clean_tmp_files, output_dir) os.rmdir(output_dir) kwargs = dict(background_match = options.background_match, combine = options.combine, bitpix=-64, ) if options.ncores > 1: kwargs['mpi'] = True # use MPI whenever possible kwargs['n_proc'] = options.ncores # number of MPI processes montage.mosaic(input_dir, output_dir, **kwargs) # montage.mosaic() writes several files to the output directory, but we are # only interested in one of them: 'mosaic.fits', the mosaic FITS image. MOSAIC_OUTPUT = 'mosaic.fits' src = os.path.join(output_dir, MOSAIC_OUTPUT) if options.reproject: print "%sReproject mosaic to point North..." % style.prefix , sys.stdout.flush() kwargs = dict(north_aligned = True, silent_cleanup = True) montage.reproject(src, output_path, **kwargs) print 'done.' else: # No reprojection, move mosaic to the output path shutil.move(src, output_path) print "%sYou're done ^_^" % style.prefix return 0
def galex(band='fuv', ra_ctr=None, dec_ctr=None, size_deg=None, index=None, name=None): tel = 'galex' data_dir = os.path.join(_TOP_DIR, tel, 'sorted_tiles') problem_file = os.path.join(_HOME_DIR, 'problem_galaxies.txt') galaxy_mosaic_file = os.path.join(_MOSAIC_DIR, '_'.join([name, band]).upper() + '.FITS') #if not os.path.exists(galaxy_mosaic_file): if name: # READ THE INDEX FILE (IF NOT PASSED IN) if index is None: indexfile = os.path.join(_INDEX_DIR, tel + '_index_file.fits') ext = 1 index, hdr = pyfits.getdata(indexfile, ext, header=True) # CALIBRATION FROM COUNTS TO ABMAG fuv_toab = 18.82 nuv_toab = 20.08 # PIXEL SCALE IN ARCSECONDS pix_as = 1.5 # galex pixel scale -- from galex docs # MAKE A HEADER pix_scale = 1.5 / 3600. # 1.5 arbitrary: how should I set it? pix_len = size_deg / pix_scale target_hdr = create_hdr(ra_ctr, dec_ctr, pix_len, pix_scale) # CALCULATE TILE OVERLAP tile_overlaps = calc_tile_overlap(ra_ctr, dec_ctr, pad=size_deg, min_ra=index['MIN_RA'], max_ra=index['MAX_RA'], min_dec=index['MIN_DEC'], max_dec=index['MAX_DEC']) # FIND OVERLAPPING TILES WITH RIGHT BAND # index file set up such that index['fuv'] = 1 where fuv and # index['nuv'] = 1 where nuv ind = np.where((index[band]) & tile_overlaps) ct_overlap = len(ind[0]) # MAKE SURE THERE ARE OVERLAPPING TILES if ct_overlap == 0: with open(problem_file, 'a') as myfile: myfile.write(name + ': ' + 'No overlapping tiles\n') return # SET UP THE OUTPUT ri_targ, di_targ = make_axes(target_hdr) sz_out = ri_targ.shape outim = ri_targ * np.nan prihdu = pyfits.PrimaryHDU(data=outim, header=target_hdr) target_hdr = prihdu.header # CREATE NEW DIRECTORY TO STORE TEMPORARY FILES gal_dir = os.path.join(_HOME_DIR, name) os.makedirs(gal_dir) infiles = infiles = index[ind[0]]['fname'] infiles = [data_dir + '/' + f for f in infiles] # CREATE SUBDIRECTORY INSIDE TEMP DIRECTORY FOR THE INPUT FILES input_dir = os.path.join(gal_dir, 'input') os.makedirs(input_dir) outfiles = [ os.path.join(input_dir, f.split('/')[-1].replace('.fits', '_mjysr.fits')) for f in infiles ] # CONVERT TO MJY/SR AND WRITE NEW FILES INTO TEMPORARY DIRECTORY for i in range(len(infiles)): im, hdr = pyfits.getdata(infiles[i], header=True) if band.lower() == 'fuv': im = counts2jy_galex(im, fuv_toab, pix_as) if band.lower() == 'nuv': im = counts2jy_galex(im, nuv_toab, pix_as) if not os.path.exists(outfiles[i]): pyfits.writeto(outfiles[i], im, hdr) # APPEND UNIT INFORMATION TO THE NEW HEADER target_hdr['BUNIT'] = 'MJY/SR' # WRITE OUT A HEADER FILE hdr_file = os.path.join(gal_dir, name + '_template.hdr') write_headerfile(hdr_file, target_hdr) final_dir = os.path.join(gal_dir, 'mosaic') # MOSAIC THE TILES FOR THIS GALAXY try: montage.mosaic(input_dir, final_dir, header=hdr_file, background_match=False, combine='count') set_trace() # COPY MOSAIC FILE TO CUTOUTS DIRECTORY mosaic_file = os.path.join(final_dir, 'mosaic.fits') newfile = '_'.join([name, band]).upper() + '.FITS' new_mosaic_file = os.path.join(_MOSAIC_DIR, newfile) shutil.copy(mosaic_file, new_mosaic_file) # REMOVE GALAXY DIRECTORY AND EXTRA FILES shutil.rmtree(gal_dir) except Exception as inst: me = sys.exc_info()[0] problem_file = os.path.join(_HOME_DIR, 'problem_galaxies.txt') with open(problem_file, 'a') as myfile: myfile.write(name + ': ' + str(me) + ': ' + str(inst) + '\n') shutil.rmtree(gal_dir) return
def galex(band='fuv', ra_ctr=None, dec_ctr=None, size_deg=None, index=None, name=None): tel = 'galex' data_dir = _FILE_DIR problem_file = os.path.join(_HOME_DIR, 'problem_galaxies.txt') galaxy_mosaic_file = os.path.join(_HOME_DIR, '_'.join([name, band]).upper() + '.FITS') if not os.path.exists(galaxy_mosaic_file): # CALIBRATION FROM COUNTS TO ABMAG fuv_toab = 18.82 nuv_toab = 20.08 # PIXEL SCALE IN ARCSECONDS pix_as = 1.5 # galex pixel scale -- from galex docs # MAKE A HEADER pix_scale = 1.5 / 3600. # 1.5 arbitrary: how should I set it? pix_len = size_deg / pix_scale target_hdr = create_hdr(ra_ctr, dec_ctr, pix_len, pix_scale) # SET UP THE OUTPUT ri_targ, di_targ = make_axes(target_hdr) sz_out = ri_targ.shape outim = ri_targ * np.nan prihdu = pyfits.PrimaryHDU(data=outim, header=target_hdr) target_hdr = prihdu.header # CREATE NEW DIRECTORY TO STORE TEMPORARY FILES gal_dir = os.path.join(_HOME_DIR, name) os.makedirs(gal_dir) infiles = glob.glob(os.path.join(_INTSUBSKYFILE_DIR, '*.fits')) bgfiles = glob.glob(os.path.join(_BGFILE_DIR, '*.fits')) rrhrfiles = glob.glob(os.path.join(_RRHRFILE_DIR, '*.fits')) # CREATE SUBDIRECTORY INSIDE TEMP DIRECTORY FOR THE INPUT FILES input_dir = os.path.join(gal_dir, 'input') os.makedirs(input_dir) outfiles = [ os.path.join(input_dir, f.split('/')[-1].replace('.fits', '_mjysr.fits')) for f in infiles ] # CONVERT TO MJY/SR AND WRITE NEW FILES INTO TEMPORARY DIRECTORY w_sum = 0. for i in range(len(infiles)): im, hdr = pyfits.getdata(infiles[i], header=True) bg = pyfits.getdata(bgfiles[i]) rrhr, rrhdr = pyfits.getdata(rrhrfiles[i], header=True) mean_bg = np.nanmean(bg[bg > 0]) med_bg = np.nanmedian(bg[bg > 0]) w = 1. / rrhr w_sum += w if band.lower() == 'fuv': im = counts2jy_galex(im, fuv_toab, pix_as) if band.lower() == 'nuv': im = counts2jy_galex(im, nuv_toab, pix_as) im -= mean_bg im *= w if not os.path.exists(outfiles[i]): pyfits.writeto(outfiles[i], im, hdr) # APPEND UNIT INFORMATION TO THE NEW HEADER target_hdr['BUNIT'] = 'MJY/SR' # WRITE OUT A HEADER FILE hdr_file = os.path.join(gal_dir, name + '_template.hdr') write_headerfile(hdr_file, target_hdr) final_dir = os.path.join(gal_dir, 'mosaic') # WRITE OUT TOTAL WEIGHT FILE weightfile = os.path.join(gal_dir, 'weights.fits') pyfits.writeto(weightfile, w_sum, rrhdr) reprojweightfile = os.path.join(gal_dir, 'reproj_weights.fits') # MOSAIC THE TILES FOR THIS GALAXY try: # THE MEAN COADD WORKS THE BEST montage.mosaic(input_dir, final_dir, header=hdr_file, background_match=True, combine='mean') montage.mProject(weightfile, reprojweightfile, hdr_file) # COPY MOSAIC FILE TO CUTOUTS DIRECTORY mosaic_file = os.path.join(final_dir, 'mosaic.fits') newmosaic_file = os.path.join(final_dir, 'weighted_mosaic.fits') im, hdr = pyfits.getdata(mosaic_file, header=True) wt = pyfits.getdata(reprojweightfile) im /= wt #set_trace() pyfits.writeto(newmosaic_file, im, hdr) sys.exit() #set_trace() # REMOVE GALAXY DIRECTORY AND EXTRA FILES shutil.rmtree(gal_dir) except Exception as inst: me = sys.exc_info()[0] problem_file = os.path.join(_HOME_DIR, 'problem_galaxies.txt') with open(problem_file, 'a') as myfile: myfile.write(name + ': ' + str(me) + ': ' + str(inst) + '\n') shutil.rmtree(gal_dir) return
#! /usr/bin/env python import montage_wrapper import sys,os if '/' in sys.argv[1]: montage_wrapper.mosaic(sys.argv[1][:-1],'mosaic') os.system('mv mosaic/mosaic.fits ../{}.fits'.format(sys.argv[1][:-1])) else: montage_wrapper.mosaic(sys.argv[1],'mosaic') os.system('mv mosaic/mosaic.fits {}.fits'.format(sys.argv[1])) os.system('rm -r mosaic')
import os import montage_wrapper as montage from glob import glob from astropy.io import fits # FITS to combine should be added into this directory path = "/media/eric/Data_3/NGC1313/HST/" raw_path = os.path.join(path, "raw_mosaic_fits") outpath = "/media/eric/Data_3/NGC1313/HST/final_mosaic" if not os.path.exists(raw_path): os.mkdir(raw_path) # Grab all of the total frames, extract the SCI extension # into the raw_mosaic_fits folder totals = glob(os.path.join(path, "*total")) for fold in totals: filename = os.path.join(fold, fold.split("/")[-1] + "_drz.fits") hdu = fits.open(filename) sci_hdu = hdu["SCI"] out_name = os.path.join(raw_path, fold.split("/")[-1] + "_sci.fits") sci_hdu.writeto(out_name) # Create the mosaic montage.mosaic(raw_path, outpath, background_match=False)
def main(arguments=None): """ main() function, encapsulated in a method to allow for easy invokation. This method follows Guido van Rossum's suggestions on how to write Python main() functions in order to make them more flexible. By encapsulating the main code of the script in a function and making it take an optional argument the script can be called not only from other modules, but also from the interactive Python prompt. Guido van van Rossum - Python main() functions: http://www.artima.com/weblogs/viewpost.jsp?thread=4829 Keyword arguments: arguments - the list of command line arguments passed to the script. """ if arguments is None: arguments = sys.argv[1:] # ignore argv[0], the script name (options, args) = parser.parse_args(args=arguments) # Print the help and abort the execution if there are fewer than three # positional arguments left, as the user must specify at least two FITS # images and the output mosaic into which they are assembled. if len(args) < 3: parser.print_help() return 2 # used for command line syntax errors else: assert len(args) >= 3 input_paths = set(args[:-1]) output_path = args[-1] # Refuse to overwrite the output FITS file unless explicitly instructed to # do so. Note that, if the --overwritten option is given, we do not need to # delete the existing file: it will be silently overwritten when the output # of montage.mosaic() is shutil.move()'d to the output path. if os.path.exists(output_path): if not options.overwrite: msg = "%sError. The output file '%s' already exists." print msg % (style.prefix, output_path) print style.error_exit_message return 1 # Workaround for a bug in montage.mosaic() that raises an error ('mpirun # has exited due to process rank [...] without calling "finalize"...') if # mpi = True and background_match = True. Until this is fixed, we can only # use one core if the --background-match option is given by the user. if options.background_match and options.ncores > 1: options.ncores = 1 for msg in ( "{0}Warning: --background-match is incompatible with --cores > 1.", "{0}Setting the --cores option to a value of one.", "{0}This is a workaround for a known bug in montage-wrapper:", "{0}https://github.com/astropy/montage-wrapper/issues/18"): print msg.format(style.prefix) print # Map each filter to a list of FITSImage objects files = fitsimage.InputFITSFiles() msg = "%sMaking sure the %d input paths are FITS images..." print msg % (style.prefix, len(input_paths)) util.show_progress(0.0) for index, path in enumerate(input_paths): # fitsimage.FITSImage.__init__() raises fitsimage.NonStandardFITS if # one of the paths is not a standard-conforming FITS file. try: img = fitsimage.FITSImage(path) # If we do not need to know the photometric filter (because the # --filter was not given) do not read it from the FITS header. # Instead, use None. This means that 'files', a dictionary, will # only have a key, None, mapping to all the input FITS images. if options.filter: pfilter = img.pfilter(options.filterk) else: pfilter = None files[pfilter].append(img) except fitsimage.NonStandardFITS: print msg = "'%s' is not a standard FITS file" raise fitsimage.NonStandardFITS(msg % path) percentage = (index + 1) / len(input_paths) * 100 util.show_progress(percentage) print # progress bar doesn't include newline # The --filter option allows the user to specify which FITS files, among # all those received as input, must be combined: only those images taken # in the options.filter photometric filter. if options.filter: msg = "%s%d different photometric filters were detected:" print msg % (style.prefix, len(files.keys())) for pfilter, images in sorted(files.iteritems()): msg = "%s %s: %d files (%.2f %%)" percentage = len(images) / len(files) * 100 print msg % (style.prefix, pfilter, len(images), percentage) msg = "%sIgnoring images not taken in the '%s' photometric filter..." print msg % (style.prefix, options.filter), sys.stdout.flush() discarded = 0 for pfilter, images in files.items(): if pfilter != options.filter: discarded += len(images) del files[pfilter] if not files: print msg = "%sError. No image was taken in the '%s' filter." print msg % (style.prefix, options.filter) print style.error_exit_message return 1 else: print 'done.' msg = "%s%d images taken in the '%s' filter, %d were discarded." print msg % (style.prefix, len(files), options.filter, discarded) # montage.mosaic() silently ignores those FITS images that have no WCS # information in their headers, and also raises a rather cryptic exception # (mMakeHdr: Invalid table file) if none of them has been astrometrically # solved. Instead of ignoring some images without warning or showing a # confusing error message that makes it almost impossible to understand # what may be failing, use FITSImage.center_wcs() to make sure that all the # images have WCS information, raising NoWCSInformationError otherwise. for img in files: # May raise NoWCSInformationError img.center_wcs() # montage.mosaic() requires as first argument the directory containing the # input FITS images but, in order to maintain the same syntax across all # LEMON commands, we receive them as command-line arguments. Thus, create a # temporary directory and symlink from it the input images. Hard links are # not an option because os.link() will raise "OSError: [Errno 18] Invalid # cross-device link" if the temporary directory is created in a different # partition. pid = os.getpid() suffix = "_LEMON_%d_mosaic" % pid kwargs = dict(suffix=suffix + '_input') input_dir = tempfile.mkdtemp(**kwargs) atexit.register(util.clean_tmp_files, input_dir) for img in files: path = img.path source = os.path.abspath(path) basename = os.path.basename(path) link_name = os.path.join(input_dir, basename) os.symlink(source, link_name) # The output of montage.mosaic() is another directory, to which several # files are written, so we need the path to a second temporary directory. # Delete it before calling mosaic(), as otherwise it will raise IOError # ("Output directory already exists"). kwargs = dict(suffix=suffix + '_output') output_dir = tempfile.mkdtemp(**kwargs) atexit.register(util.clean_tmp_files, output_dir) os.rmdir(output_dir) kwargs = dict( background_match=options.background_match, combine=options.combine, bitpix=-64, ) if options.ncores > 1: kwargs['mpi'] = True # use MPI whenever possible kwargs['n_proc'] = options.ncores # number of MPI processes montage.mosaic(input_dir, output_dir, **kwargs) # montage.mosaic() writes several files to the output directory, but we are # only interested in one of them: 'mosaic.fits', the mosaic FITS image. MOSAIC_OUTPUT = 'mosaic.fits' src = os.path.join(output_dir, MOSAIC_OUTPUT) if options.reproject: print "%sReproject mosaic to point North..." % style.prefix, sys.stdout.flush() kwargs = dict(north_aligned=True, silent_cleanup=True) montage.reproject(src, output_path, **kwargs) print 'done.' else: # No reprojection, move mosaic to the output path shutil.move(src, output_path) print "%sYou're done ^_^" % style.prefix return 0
import os import montage_wrapper as montage from glob import glob from astropy.io import fits # FITS to combine should be added into this directory path = "/media/eric/Data_3/NGC1313/HST/" raw_path = os.path.join(path, "raw_mosaic_fits") outpath = "/media/eric/Data_3/NGC1313/HST/final_mosaic" if not os.path.exists(raw_path): os.mkdir(raw_path) # Grab all of the total frames, extract the SCI extension # into the raw_mosaic_fits folder totals = glob(os.path.join(path, "*total")) for fold in totals: filename = os.path.join(fold, fold.split("/")[-1]+"_drz.fits") hdu = fits.open(filename) sci_hdu = hdu["SCI"] out_name = os.path.join(raw_path, fold.split("/")[-1]+"_sci.fits") sci_hdu.writeto(out_name) # Create the mosaic montage.mosaic(raw_path, outpath, background_match=False)