Esempio n. 1
0
def trim(args):
    # Define region to be trimmed
    y0, y1, x0, x1 = args.region

    # args.output should be a list of output names. If they do not exist, the outputs should be the same as the
    # inputs with whatever suffix, if any, the user gave
    if not args.output:
        args.output = [utilities.add_suffix_prefix(im_name, suffix=args.suffix) for im_name in args.input]

    # Do the actual trimming. We will do it first into a temporary file, then copy it into args.output. This is just
    # in case the output and input filenames are the same, or if the output exists. IRAF will not overwrite!
    for im_name, new_name in zip(args.input, args.output):
        basename = os.path.splitext(os.path.basename(im_name))[0]
        _, temp_output = tempfile.mkstemp(prefix=basename, suffix=".fits")
        os.unlink(temp_output )
        with utilities.tmp_mute():
            imcopy(im_name + "[{0}:{1}, {2}:{3}]".format(x0, x1, y0, y1), temp_output)
            shutil.move(temp_output, new_name)

            # If a mask exists, trim exactly equally
            if args.mask_key:
                maskname = fits.getheader(im_name)[args.mask_key]
                with fits.open(maskname, 'readonly') as mask_im:
                    mask_im[0].data = mask_im[0].data[y0:y1+1, x0:x1+1]
                    mask_output = utilities.replace_extension(new_name, ".fits.msk")
                    fits.writeto(mask_output, mask_im[0].data, mask_im[0].header, clobber=True)
                utilities.header_update_keyword(new_name, "MASK", os.path.abspath(mask_output),
                                                comment="Name of mask image. ")

    return args.output
Esempio n. 2
0
def match(args):
    """ Match the PSF of a group of images with the PSF of a reference image.
    """
    sort_by_seeing(args)

    # Get seeing from header and calculate psf of reference image, the first one since we sorted the input
    ref_seeing = utils.get_from_header(args.input[0], args.FWHM_key)
    ref_psf = psf.main(arguments=[args.input[0], "--stars", args.input_stars[0],
                                  "--sigma_key", args.sigma,
                                  "--gain_key",  args.gain_key,  
                                  "--ron_key",   args.ron_key,  
                                  "--expt_key",  args.expt_key, 
                                  "--airm_key",  args.airm_key, 
                                  "--FWHM_key", args.FWHM_key])
 
    output_list = []
    for image, stars in zip(args.input, args.input_stars):
        output = utils.add_suffix_prefix(image, suffix=args.suffix)

        # Too small differences of seeing are not worh doing any matching
        current_seeing = utils.get_from_header(image, args.FWHM_key)
        if abs(ref_seeing - current_seeing) < args.limit:  # Not worth equating PSFs for small differences
            shutil.copy(image, output)  # copy old file into new one
        else:
            # Calculate psf of the other images
            psf_object =  psf.main(arguments=[image,
                                              "--stars",     stars,
                                              "--sigma_key", args.sigma,
                                              "--gain_key",  args.gain_key,
                                              "--ron_key",   args.ron_key,
                                              "--expt_key",  args.expt_key,
                                              "--airm_key",  args.airm_key,
                                              "--FWHM_key", args.FWHM_key])
            utils.if_exists_remove("kernel.fits", output)
            iraf.psfmatch(image, ref_psf, psf_object, "kernel.fits",
                                 convolution="psf", 
                                 filter="cosbell")                   
            iraf.psfmatch(image, ref_psf, psf_object,
                                 convolution="kernel", 
                                 kernel="kernel.fits", 
                                 output=output,
                                 verbose="no")
            utils.if_exists_remove("kernel.fits")
            mssg = "Before equating PSFs: " + str(current_seeing)
            utils.header_update_keyword(output, args.FWHM_key, ref_seeing, comment=mssg)
        output_list.append(output)
    return output_list
Esempio n. 3
0
def calculate_seeing(args):
    """ Program to estimate the seeing from an image and a list of estimates
    for the positions of stars. After calculating the seeing, some of the 
    stars might get recalculated centers. The list will be updated with the 
    """
    for im, im_cat in zip(args.input, args.cat):
        output = "output.txt"
        ignore = "ignore.txt"
        # Victor Terron, esto es horroroso, sugerencias?
        utilities.if_exists_remove("q.txt", output, ignore)
        q = open("q.txt", "w")
        q.write("q")
        q.close()
        iraf.noao()
        iraf.obsutil()
        iraf.module.psfmeasure(im, coords = "mark1", size = "MFWHM", 
                               sbuffer = 10, swidth=10,radius=10,
                               satura = 55000, ignore = "yes", 
                               imagecur = im_cat, display = "no", 
                               graphcur = "q.txt", Stdout=ignore, 
                               wcs = args.wcs, logfile=output)
        
        # Now we read the input im_cat and the output output.txt and compare
        # the location of stars. Those stars that have moved will not be 
        # trusted. 
        xout = np.array([])
        yout = np.array([])
        FWHM = np.array([])
        for line in open(output, 'r'):
            # First line is a description of the file, second is a newline \n
            # and third the description of the columns.
            if line != "\n" and line.split()[0] in im:
                xout = np.append(xout, float(line.split()[1]))
                yout = np.append(yout, float(line.split()[2]))
                FWHM = np.append(FWHM, float(line.split()[4]))
            else:
                try:
                   xout = np.append(xout, float(line.split()[0])) 
                   yout = np.append(yout, float(line.split()[1]))
                   FWHM = np.append(FWHM, float(line.split()[3]))
                except:
                   pass 
        xin, yin = np.genfromtxt(im_cat, dtype="float", unpack=True)
        xin, yin = np.array(xin), np.array(yin)  # case it is only one value


        # If args.wcs is "world" it means the input is in (RA, DEC), while 
        # the output is in pixels (X,Y). We need to convert one to the other
        # and we choose to follow the (RA,DEC) which, after all, is meaningful
        if args.wcs == "world":
            coords_xy = np.array(zip(xout, yout))
            hdr = fits.open(im)[0].header
            remove_keys = ["PC001001", "PC001002", "PC002001", "PC002002"]
            for keys in remove_keys:
                hdr.pop(keys,None)
            w = wcs.WCS(hdr)            
            coords_RADEC = w.all_pix2world(coords_xy,1)
            xout = coords_RADEC[:,0]
            yout = coords_RADEC[:,1]
           
        # find common stars using KDtrees    
        if xin.size > 1 : 
            tree_in = spatial.KDTree(zip(xin, yin))
        elif xin.size == 1:
            tree_in = spatial.KDTree([(float(xin), float(yin))])
        if xout.size > 1:
            tree_out = spatial.KDTree(zip(xout, yout))
        elif xout.size == 1:
            tree_out = spatial.KDTree([(float(xout), float(yout))]) 
        # If WCS use 0.001 degree (~3.6 arcsec) as limit. If not, assume 
        # pixels and say 4 pixels
        if args.wcs == "world":
            limit = 0.001
        else:
            limit = 4
        matches = tree_out.query_ball_tree(tree_in, limit) 
           
        # Two close stars in the original .cat could resolve into one  when 
        # the FWHM is calculated. This will appear as several hits in the 
        # matches with exactly the same numbers: [[0], [1,2], [1,2], [3]]
        # One solution is to erase one of them 
        for index, value in enumerate(matches):      
            if matches.count(value) > 1:
                matches[index] = []
                       
        # Now restrict to the common objects
        remove_indices = [ii for ii,jj in enumerate(matches) if jj == []]
        xout = np.delete(xout, remove_indices)
        yout = np.delete(yout, remove_indices)
        FWHM = np.delete(FWHM, remove_indices)
 
        # Finally, calculate the median FWHM of the image and rewrite valid
        # stars to the im_cat file. 
        median_fwhm = np.median(FWHM)
        utilities.header_update_keyword(im, "seeing", median_fwhm, "FWHM of image")
        f = open(im_cat, 'w') # write the "good" stars in the catalogue
        for ii in range(len(xout)):
            f.write(str(xout[ii]) + "  " + str(yout[ii]) + "\n")
        f.close()

        # And clean after yourself!
        utilities.if_exists_remove("q.txt", output, ignore)
Esempio n. 4
0
        os.chdir(lemon_dir)
        import lemon.seeing as seeing
        seeing.main(arguments=["--margin", "0", "--filename", '', "--suffix",
                               "-s", image, os.path.split(image)[0] ])
        newname = utilities.add_suffix_prefix(image, suffix = "-s")

        os.chdir(curdir)
        list_images["filename"][index] = newname
            
        # While running lemon.seeing a sextractor catalogue is produced. 
        catalog = fits.getheader(newname)["SEX CATALOG"]
        catalog_newname = utilities.replace_extension(newname, ".cat")
        shutil.copy(catalog, catalog_newname)
        # Damn FITS format and its constraints!
        short_name = os.path.split(catalog_newname)[1]
        utilities.header_update_keyword(newname, "SEX CATALOG", short_name)

print "Estimate sky for images of CIG(s), standard(s) and cluster(s) "
for index, image in enumerate(list_images["filename"]):
    if list_images["type"][index] in ["cig","standards","clusters"]:
        find_sky.main(arguments=[list_images["filename"][index]])

print "Detecting objects for images of CIG(s), standard(s) and cluster(s)"
# This part follows the example in the webpage:
#http://www.lancesimms.com/programs/Python/pyraf/daofind.py
for index, image in enumerate(list_images["filename"]):
    if list_images["type"][index] in ["cig","standards","clusters"]:
        outfile = utilities.replace_extension(image, ".cat")
        if os.path.isfile(outfile):
            os.remove(outfile)
        # Prepare and run daofind
Esempio n. 5
0
def combine(args):
    # Create the folders that do not already exist for the output file
    outdir, outfile = os.path.split(os.path.abspath(args.output))
    if outdir == "":
        outdir = "."

    utils.if_dir_not_exists_create(outdir)

    # Build a list of the filter of each image
    #filter_list, images_filters = build_filter_list(args)
    images_filters = utils.collect_from_images(args.input, args.filterk)

    # If user wants all images to be combined together, regardless of filter:
    if args.all_together:
        images_filters = ["AllFilters"] * len(images_filters)

    # Create a default dictionary for the resulting images
    result = collections.defaultdict(str)    
    
    # For each of the filters present combine the images (and write)
    for filt in set(images_filters):
        # list of objects with current filter (exception: allfilters is true)
        list1 = [args.input[p] for p,f in enumerate(images_filters) if f == filt ]

        # Check that all images have same dimension. If not, exit program
        if not utils.check_dimensions(list1):
            sys.exit("Dimensions of images to combine are different!")

        # Calculate scale of images
        scales = compute_scales(list1, args.scale, args.mask_key)


        # Get the sizes of the images
        lx, ly = utils.get_from_header(list1[0], "NAXIS2", "NAXIS1")

        # Now, in order to avoid loading many images in memory, we need to slice the images in pieces and combine a slice
        # of all the images at a time
        n_slices = 32          # divide the slow axis in this many pieces

        # Define the whole image and set all elements of mask to False
        whole_image = numpy.ma.zeros([lx,ly])
        whole_image.mask = numpy.zeros_like(whole_image.data)

        for xmin in range(0, lx, lx/n_slices):
            xmax = min(xmin + lx/n_slices, lx)

            # Now we can build and sort a section of the cube with all the images
            cube = cube_images(list1, args.mask_key, scales, limits=[xmin, 0, xmax, ly])
            cube.sort(axis=0)

            # Finally, average! Remember that the cube is sorted so that
            # cube[0,ii,jj] < cube[1,ii,jj] and that the highest values of all
            # are the masked elements. We will take advantage of it if the median
            # is selected, because nowadays the masked median is absurdly slow:
            # https://github.com/numpy/numpy/issues/1811
            map_cube = numpy.ma.count(cube, axis=0) # number non-masked values per pixel
            if args.average == "mean":
                image = numpy.ma.mean(cube, axis=0)
                non_masked_equivalent = numpy.mean(cube.data, axis=0)
            elif args.average == "median":
                image = home_made_median(map_cube, cube)
                non_masked_equivalent = numpy.median(cube.data, axis=0)

            # Image is a masked array, we need to fill in masked values with the
            # args.fill_val if user provided it. Also, values with less than
            # args.nmin valid values should be masked out. If user did not provide
            # a fill_val argument, we will substitute masked values with the
            # unmasked equivalent operation.
            image.mask[map_cube < args.nmin] = 1
            mask = image.mask
            if args.fill_val != '':
                image = image.filled(args.fill_val)
            else:
                image.data[mask == True] = non_masked_equivalent[mask == True]
                image = image.data

            whole_image.data[xmin:xmax, 0:ly] = image[:,:]
            whole_image.mask[xmin:xmax, 0:ly] = mask[:,:]

        # And save images. If all_together is activated, use the file name given by user. If not, we need
        # to separate by filter, so compose a new name with the one given by the user adding the filter
        if args.all_together:
            newfile = args.output
        else:
            newfile = os.path.join(outdir, utils.add_suffix_prefix(outfile, suffix="_" + filt) )

        if args.out_mask != "":
            name_mask = args.out_mask
        else:
            name_mask = newfile + ".msk"
        if os.path.isfile(newfile):
            os.remove(newfile)
        if os.path.isfile(name_mask):
            os.remove(name_mask)
        fits.writeto(newfile, whole_image.data)
        fits.writeto(name_mask, whole_image.mask.astype(numpy.int))
        result[filt] = newfile

        # Add comments to the headers
        string1 = " - Image built from the combination of the images: "+\
                 ", ".join(list1)
        string2 = " combine = " + args.average + ", scale = " + args.scale
        utils.add_history_line(newfile, string1 + string2 )
        utils.add_history_line(name_mask, " - Mask of image: " + newfile)
        if args.mask_key != "":
            utils.header_update_keyword(newfile, args.mask_key, name_mask,
                                        "Mask for this image")

        # To normalize calculate median and call arith_images to divide by it.
        if args.norm == True:
            median = compute_scales([newfile], args.scale, args.mask_key)[0]
            msg =  "- NORMALIZED USING MEDIAN VALUE:"
            arith_images.main(arguments=["--message", msg, "--output", newfile,
                                         "--mask_key", args.mask_key, "--fill_val",
                                         args.fill_val, newfile, "/", str(median)])
    return result
Esempio n. 6
0

if os.path.exists( os.path.join(directory, 'cig') ):
    list_images = search_images(directory)
else:
    print "Rename files"
    list_images = rename.main(arguments=["--copy", "--objectk", objectk,\
                                         "--filterk", filterk, "--datek", datek,\
                                         "--overwrite", "--exptime", exptimek,\
                                         directory])

print "Include homogeneous filter names into the filter keyword"
for im in list_images["filename"]:
    imfilt = utilities.get_from_header(im, filterk)
    imfilt2 = utilities.homogeneous_filter_name(imfilt)
    utilities.header_update_keyword(im, filterk+"_OLD", imfilt, "Original filter name")
    utilities.header_update_keyword(im, filterk,        imfilt2, "Revised filter name")
    

print "Ignore images as selected by user, if any."
try:
    for im in remove_images:
        index = [i for i,v in enumerate(list_images["filename"]) if str(im) in v]
        for key in list_images.keys():  # remove that item from all the lists
            list_images[key] = np.delete(list_images[key], index)
except NameError: # variable remove_images not defined
    pass


print "Create masks for images"
for ii,im in enumerate(list_images["filename"]):
Esempio n. 7
0
                                                                        "--expt_key", exptimek,
                                                                        "--airm_key", airmassk,
                                                                        "--FWHM_k", seeingk] + obj_images)
    list_images["filename"][np.where(list_images["objname"] == obj)] = output_images


print "Normalize using exposure time. "
for ii, im_name in enumerate(list_images["filename"]):
    if list_images["type"][ii] in ["cig", "clusters"]:
        tt = float(utils.get_from_header(im_name, exptimek))
        newname = utils.add_suffix_prefix(im_name, suffix="-t")
        mssg = "Normalized to exptime (divided by " + str(tt) + ")"
        arith_images.main(arguments=["--output", newname, "--message", mssg, "--mask_key", "MASK", im_name, "/", str(tt)])
        mssg = "Before normalizing: " + str(tt)
        # Update values for the exptime, the sky, the sky std...
        utils.header_update_keyword(newname, exptimek, 1, mssg)
        ss = float(utils.get_from_header(im_name, skyk))
        utils.header_update_keyword(newname, skyk, ss/tt)
        ss_std = float(utils.get_from_header(im_name, sky_stdk))
        utils.header_update_keyword(newname, sky_stdk, ss_std/tt)
        list_images["filename"][ii] = newname


print "Correct for atmospheric extinction."
for ii, im_name in enumerate(list_images["filename"]):
    if list_images["type"][ii] in ["cig", "clusters", "standards"]:
        airmass = float(utils.get_from_header(im_name, airmassk))
        correcting_factor = 10**(ext_coeff * airmass / 2.5)
        newname = utils.add_suffix_prefix(im_name, suffix="-e")
        mssg = "Corrected from atmospheric extinction. Coefficient: " + str(ext_coeff)
        arith_images.main(arguments=["--output", newname,
Esempio n. 8
0
                                                                        "--expt_key", exptimek,
                                                                        "--airm_key", airmassk,
                                                                        "--FWHM_k", seeingk] + obj_images)
    list_images["filename"][np.where(list_images["objname"] == obj)] = output_images


print "Normalize using exposure time. "
for ii, im_name in enumerate(list_images["filename"]):
    if list_images["type"][ii] in ["cig", "clusters"]:
        tt = float(utils.get_from_header(im_name, exptimek))
        newname = utils.add_suffix_prefix(im_name, suffix="-t")
        mssg = "Normalized to exptime (divided by " + str(tt) + ")"
        arith_images.main(arguments=["--output", newname, "--message", mssg, "--mask_key", "MASK", im_name, "/", str(tt)])
        mssg = "Before normalizing: " + str(tt)
        # Update values for the exptime, the sky, the sky std...
        utils.header_update_keyword(newname, exptimek, 1, mssg)
        ss = float(utils.get_from_header(im_name, skyk))
        utils.header_update_keyword(newname, skyk, ss/tt)
        ss_std = float(utils.get_from_header(im_name, sky_stdk))
        utils.header_update_keyword(newname, sky_stdk, ss_std/tt)
        list_images["filename"][ii] = newname


print "Correct for atmospheric extinction."
for ii, im_name in enumerate(list_images["filename"]):
    if list_images["type"][ii] in ["cig", "clusters", "standards"]:
        airmass = float(utils.get_from_header(im_name, airmassk))
        correcting_factor = 10**(ext_coeff * airmass / 2.5)
        newname = utils.add_suffix_prefix(im_name, suffix="-e")
        mssg = "Corrected from atmospheric extinction. Coefficient: " + str(ext_coeff)
        arith_images.main(arguments=["--output", newname,
Esempio n. 9
0
def arith(args):
    output_list = []        
    for operand1, operand2 in zip(args.input1, args.input2):
        # Read inputs as masked arrays or numbers (input2 might be a scalar)  
        im1 = utils.read_image_with_mask(operand1, args.mask_key)
        try: # if second operand is a number we still need it in a masked array
            value2 = numpy.ma.array([float(operand2)],mask=[0])
        except (ValueError,TypeError):
            value2 = utils.read_image_with_mask(operand2, args.mask_key)

        # If --keyword was passed, read from the header of the image the value and use it, instead of the full image
        if args.keyword:
            value2 = numpy.ma.array( fits.getval(operand2, args.keyword) )

        # Do the actual operation. Result is a masked array which masks 
        # any pixel if it is masked either in im1 or in im2.
        operations = {"+":operator.add, 
                      "-":operator.sub, 
                      "*":operator.mul,
                      "/":operator.div,
                      "**":operator.pow}

        # Case of mean or median for Input2 
        if args.median == True:
            value2 = numpy.ma.median(value2)
        elif args.mean == True:
            value2 = numpy.ma.mean(value2)

        oper = operations[args.operation[0]]
        result = numpy.zeros_like(im1)

        result.data[:] = oper(im1.data, value2.data)  # Actual operation of images
        result.mask[:] = im1.mask | value2.mask       # If any is masked, result is masked as well


        # If args.fill_val is present, use it
        if args.fill_val:
            result.data[:] = result.filled(float(args.fill_val))
                    
        # If output exists use it, otherwise use the input. Prefix/suffix might
        # modify things in next step.
        if args.output != '': 
            outpt = os.path.abspath(args.output)
        else:
            outpt = os.path.abspath(operand1)
            
        # Separate (path, file) and (file root, extensions). Then build new name. 
        outdir, outfile = os.path.split(outpt)   
        outfile_root, outfile_ext = re.match(r'(^.*?)(\..*)', outfile).groups()   
        outpt = os.path.join(outdir, args.prefix + outfile_root + args.suffix + 
                             outfile_ext)                         

        # Now name for the mask, if the name exists, use it, otherwise build it.
        if args.mask_name != "":
            mask_name = args.mask_name
        else:
            mask_name = outpt + ".msk"

        # Prepare a header starting from input1 header
        hdr_im = fits.getheader(operand1)
        name2 = os.path.split(operand2)[1]
        if args.median:  # if single number because median used
            name2 = "median(" + name2 + ") (" + str(value2) + ")"
        elif args.mean:  # if single number because mean used
            name2 = "mean(" + name2 + ") (" + str(value) + ")"

        # Write a HISTORY element to the header    
        #hdr_im.add_history(" - Operation performed: " + image1 + " " +
        #                   args.operation[0] + " " + name2)
        try:
            hdr_mask = fits.PrimaryHDU(result.mask.astype(int)).header
        except:
            pass
        hdr_mask.add_history("- Mask corresponding to image: " + outpt)

        # Update the keyword if asked by user
        if args.update and args.keyword:
            old_keyword = hdr_im[args.keyword]
            hdr_im[args.keyword] = (oper(old_keyword, value2.data), "Before: {0}".format(old_keyword) )

        # Now save the resulting image and mask
        if os.path.isfile(outpt):
            os.remove(outpt)
        if os.path.isfile(mask_name):
            os.remove(mask_name)
        fits.writeto(outpt, result.data, header=hdr_im) 
        fits.writeto(mask_name, result.mask.astype(numpy.int0), header=hdr_mask)
        utils.header_update_keyword(outpt, "MASK", os.path.abspath(mask_name),
                                                comment="Name of mask image. ")
        output_list.append(outpt)
    return output_list
Esempio n. 10
0
                                                                        "--expt_key", exptimek,
                                                                        "--airm_key", airmassk,
                                                                        "--FWHM_k", seeingk] + obj_images)
    list_images["filename"][np.where(list_images["objname"] == obj)] = output_images


print "Normalize using exposure time. "
for ii, im_name in enumerate(list_images["filename"]):
    if list_images["type"][ii] in ["cig", "clusters"]:
        tt = float(utils.get_from_header(im_name, exptimek))
        newname = utils.add_suffix_prefix(im_name, suffix="-t")
        mssg = "Normalized to exptime (divided by " + str(tt) + ")"
        arith_images.main(arguments=["--output", newname, "--message", mssg, "--mask_key", "MASK", im_name, "/", str(tt)])
        mssg = "Before normalizing: " + str(tt)
        # Update values for the exptime, the sky, the sky std...
        utils.header_update_keyword(newname, exptimek, 1, mssg)
        ss = float(utils.get_from_header(im_name, skyk))
        utils.header_update_keyword(newname, skyk, ss/tt)
        ss_std = float(utils.get_from_header(im_name, sky_stdk))
        utils.header_update_keyword(newname, skyk, ss_std/tt)
        list_images["filename"][ii] = newname


print "Correct for atmospheric extinction."
for ii, im_name in enumerate(list_images["filename"]):
    if list_images["type"][ii] in ["cig", "clusters", "standards"]:
        airmass = float(utils.get_from_header(im_name, airmassk))
        correcting_factor = 10**(ext_coeff * airmass / 2.5)
        newname = utils.add_suffix_prefix(im_name, suffix="-e")
        mssg = "Corrected from atmospheric extinction. Coefficient: " + str(ext_coeff)
        arith_images.main(arguments=["--output", newname,