Skip to content

Problems with running astrosource on STELLA telescope data #20

@turchis

Description

@turchis

Hello,

I'm trying to run inside a directory with already reduced and SEP embedded data (acquired from STELLA telescope) the following command:
'astrosource --ra 330.210 --dec 7.060 --indir /export/work/marcotu/COBIPULSE-North/STELLA/DATA/reduced/J2212/gfilter/ --format fits --full --lowcounts 1000 --hicounts 50000 --thresholdcounts 1000000 --closerejectd 5.0'
but I get the error message:
'CRITICAL | No files of type ".fits" found in /export/work/marcotu/COBIPULSE-North/STELLA/DATA/reduced/J2212/gfilter/'

Since this dataset was already reduced, before running astrosource I didn't run the entire BANZAI pipeline, but just the commands for performing the source extraction and append the catalogue of detected sources in all the images. These commands are found in the script photometry.py of the BANZAI package https://github.com/LCOGT/banzai, and I just readjusted these in the following script:
'import logging
from urllib.parse import urljoin

import numpy as np
from astropy.table import Table
from astropy.io import fits
from astropy.utils.data import get_pkg_data_filename
import sep
from requests import HTTPError

from banzai.utils import stats, array_utils
from banzai.utils.photometry_utils import get_reference_sources, match_catalogs, to_magnitude, fit_photometry
from banzai.data import DataTable

from skimage import measure

sep.set_sub_object_limit(int(1e6))

def radius_of_contour(contour, source):
x = contour[:, 1]
y = contour[:, 0]
x_center = (source['xmax'] - source['xmin'] + 1) / 2.0 - 0.5
y_center = (source['ymax'] - source['ymin'] + 1) / 2.0 - 0.5

return np.percentile(np.sqrt((x - x_center)**2.0 + (y - y_center)** 2.0), 90)

def photometry(image,image_file,threshold,min_area):

        # Increase the internal buffer size in sep. This is most necessary for crowded fields.
        ny, nx = image[0].data.shape
        sep.set_extract_pixstack(int(nx * ny - 1))

        data = image[0].data

        # Fits can be backwards byte order, so fix that if need be and subtract
        # the background
        try:
            bkg = sep.Background(data, bw=64, bh=64, fw=3, fh=3)
        except ValueError:
            data = data.byteswap(True).newbyteorder()
            bkg = sep.Background(data, bw=64, bh=64, fw=3, fh=3)
        bkg.subfrom(data)
        bkg_rms = bkg.rms()

        # Do an initial source detection
        sources = sep.extract(data, threshold, minarea=min_area, deblend_cont=0.005, err=bkg_rms)


        # Convert the detections into a table
        sources = Table(sources)

        # We remove anything with a detection flag >= 8
        # This includes memory overflows and objects that are too close the edge
        sources = sources[sources['flag'] < 8]

        sources = array_utils.prune_nans_from_table(sources)

        # Calculate the ellipticity
        sources['ellipticity'] = 1.0 - (sources['b'] / sources['a'])

        # Fix any value of theta that are invalid due to floating point rounding
        # -pi / 2 < theta < pi / 2
        sources['theta'][sources['theta'] > (np.pi / 2.0)] -= np.pi
        sources['theta'][sources['theta'] < (-np.pi / 2.0)] += np.pi

        # Calculate the kron radius
        kronrad, krflag = sep.kron_radius(data, sources['x'], sources['y'],
                                          sources['a'], sources['b'],
                                          sources['theta'], 6.0)
        sources['flag'] |= krflag
        sources['kronrad'] = kronrad

        # Calcuate the equivilent of flux_auto
        flux, fluxerr, flag = sep.sum_ellipse(data, sources['x'], sources['y'],
                                              sources['a'], sources['b'],
                                              np.pi / 2.0, 2.5 * kronrad,
                                              subpix=1, err=bkg_rms)
        sources['flux'] = flux
        sources['fluxerr'] = fluxerr
        sources['flag'] |= flag

        # Do circular aperture photometry for diameters of 1" to 6"
        pixel_scale = 0.32
        for diameter in [1, 2, 3, 4, 5, 6]:
            flux, fluxerr, flag = sep.sum_circle(data, sources['x'], sources['y'],
                                                 diameter / 2.0 / pixel_scale, gain=1.0, err=bkg_rms)
            sources['fluxaper{0}'.format(diameter)] = flux
            sources['fluxerr{0}'.format(diameter)] = fluxerr
            sources['flag'] |= flag

        # Measure the flux profile
        flux_radii, flag = sep.flux_radius(data, sources['x'], sources['y'],
                                           6.0 * sources['a'], [0.25, 0.5, 0.75],
                                           normflux=sources['flux'], subpix=5)
        sources['flag'] |= flag
        sources['fluxrad25'] = flux_radii[:, 0]
        sources['fluxrad50'] = flux_radii[:, 1]
        sources['fluxrad75'] = flux_radii[:, 2]

        # Cut individual bright pixels. Often cosmic rays
        sources = sources[sources['fluxrad50'] > 0.5]

        # Calculate the FWHMs of the stars:
        sources['fwhm'] = np.nan
        sources['fwtm'] = np.nan
        # Here we estimate contours
        for source in sources:
            if source['flag'] == 0:
                for ratio, keyword in zip([0.5, 0.1], ['fwhm', 'fwtm']):
                    contours = measure.find_contours(data[source['ymin']: source['ymax'] + 1,
                                                     source['xmin']: source['xmax'] + 1],
                                                     ratio * source['peak'])
                    if contours:
                        # If there are multiple contours like a donut might have take the outer
                        contour_radii = [radius_of_contour(contour, source) for contour in contours]
                        source[keyword] = 2.0 * np.nanmax(contour_radii)

        # Calculate the windowed positions
        sig = 2.0 / 2.35 * sources['fwhm']
        xwin, ywin, flag = sep.winpos(data, sources['x'], sources['y'], sig)
        sources['flag'] |= flag
        sources['xwin'] = xwin
        sources['ywin'] = ywin

        # Calculate the average background at each source
        bkgflux, fluxerr, flag = sep.sum_ellipse(bkg.back(), sources['x'], sources['y'],
                                                 sources['a'], sources['b'], np.pi / 2.0,
                                                 2.5 * sources['kronrad'], subpix=1)
        # masksum, fluxerr, flag = sep.sum_ellipse(mask, sources['x'], sources['y'],
        #                                         sources['a'], sources['b'], np.pi / 2.0,
        #                                         2.5 * kronrad, subpix=1)

        background_area = (2.5 * sources['kronrad']) ** 2.0 * sources['a'] * sources['b'] * np.pi # - masksum
        sources['background'] = bkgflux
        sources['background'][background_area > 0] /= background_area[background_area > 0]
        # Update the catalog to match fits convention instead of python array convention
        sources['x'] += 1.0
        sources['y'] += 1.0

        sources['xpeak'] += 1
        sources['ypeak'] += 1

        sources['xwin'] += 1.0
        sources['ywin'] += 1.0

        sources['theta'] = np.degrees(sources['theta'])

        catalog = sources['x', 'y', 'xwin', 'ywin', 'xpeak', 'ypeak',
                          'flux', 'fluxerr', 'peak', 'fluxaper1', 'fluxerr1',
                          'fluxaper2', 'fluxerr2', 'fluxaper3', 'fluxerr3',
                          'fluxaper4', 'fluxerr4', 'fluxaper5', 'fluxerr5',
                          'fluxaper6', 'fluxerr6', 'background', 'fwhm', 'fwtm',
                          'a', 'b', 'theta', 'kronrad', 'ellipticity',
                          'fluxrad25', 'fluxrad50', 'fluxrad75',
                          'x2', 'y2', 'xy', 'flag']

        # Add the units and description to the catalogs
        catalog['x'].unit = 'pixel'
        catalog['x'].description = 'X coordinate of the object'
        catalog['y'].unit = 'pixel'
        catalog['y'].description = 'Y coordinate of the object'
        catalog['xwin'].unit = 'pixel'
        catalog['xwin'].description = 'Windowed X coordinate of the object'
        catalog['ywin'].unit = 'pixel'
        catalog['ywin'].description = 'Windowed Y coordinate of the object'
        catalog['xpeak'].unit = 'pixel'
        catalog['xpeak'].description = 'X coordinate of the peak'
        catalog['ypeak'].unit = 'pixel'
        catalog['ypeak'].description = 'Windowed Y coordinate of the peak'
        catalog['flux'].unit = 'count'
        catalog['flux'].description = 'Flux within a Kron-like elliptical aperture'
        catalog['fluxerr'].unit = 'count'
        catalog['fluxerr'].description = 'Error on the flux within Kron aperture'
        catalog['peak'].unit = 'count'
        catalog['peak'].description = 'Peak flux (flux at xpeak, ypeak)'
        for diameter in [1, 2, 3, 4, 5, 6]:
            catalog['fluxaper{0}'.format(diameter)].unit = 'count'
            catalog['fluxaper{0}'.format(diameter)].description = 'Flux from fixed circular aperture: {0}" diameter'.format(diameter)
            catalog['fluxerr{0}'.format(diameter)].unit = 'count'
            catalog['fluxerr{0}'.format(diameter)].description = 'Error on Flux from circular aperture: {0}"'.format(diameter)

        catalog['background'].unit = 'count'
        catalog['background'].description = 'Average background value in the aperture'
        catalog['fwhm'].unit = 'pixel'
        catalog['fwhm'].description = 'FWHM of the object'
        catalog['fwtm'].unit = 'pixel'
        catalog['fwtm'].description = 'Full-Width Tenth Maximum'
        catalog['a'].unit = 'pixel'
        catalog['a'].description = 'Semi-major axis of the object'
        catalog['b'].unit = 'pixel'
        catalog['b'].description = 'Semi-minor axis of the object'
        catalog['theta'].unit = 'degree'
        catalog['theta'].description = 'Position angle of the object'
        catalog['kronrad'].unit = 'pixel'
        catalog['kronrad'].description = 'Kron radius used for extraction'
        catalog['ellipticity'].description = 'Ellipticity'
        catalog['fluxrad25'].unit = 'pixel'
        catalog['fluxrad25'].description = 'Radius containing 25% of the flux'
        catalog['fluxrad50'].unit = 'pixel'
        catalog['fluxrad50'].description = 'Radius containing 50% of the flux'
        catalog['fluxrad75'].unit = 'pixel'
        catalog['fluxrad75'].description = 'Radius containing 75% of the flux'
        catalog['x2'].unit = 'pixel^2'
        catalog['x2'].description = 'Variance on X coordinate of the object'
        catalog['y2'].unit = 'pixel^2'
        catalog['y2'].description = 'Variance on Y coordinate of the object'
        catalog['xy'].unit = 'pixel^2'
        catalog['xy'].description = 'XY covariance of the object'
        catalog['flag'].description = 'Bit mask of extraction/photometry flags'

        catalog.sort('flux')
        catalog.reverse()

        # Save some background statistics in the header
        mean_background = stats.sigma_clipped_mean(bkg.back(), 5.0)
        image[0].header['L1MEAN'] = (mean_background,
                                '[counts] Sigma clipped mean of frame background')

        median_background = np.median(bkg.back())
        image[0].header['L1MEDIAN'] = (median_background,
                                  '[counts] Median of frame background')

        std_background = stats.robust_standard_deviation(bkg.back())
        image[0].header['L1sigma'] = (std_background,
                                 '[counts] Robust std dev of frame background')

        # Save some image statistics to the header
        good_objects = catalog['flag'] == 0
        for quantity in ['fwhm', 'ellipticity', 'theta']:
            good_objects = np.logical_and(good_objects, np.logical_not(np.isnan(catalog[quantity])))
        if good_objects.sum() == 0:
            image[0].header['L1FWHM'] = ('NaN', '[arcsec] Frame FWHM in arcsec')
            image[0].header['L1FWTM'] = ('NaN', 'Ratio of FWHM to Full-Width Tenth Max')

            image[0].header['L1ELLIP'] = ('NaN', 'Mean image ellipticity (1-B/A)')
            image[0].header['L1ELLIPA'] = ('NaN', '[deg] PA of mean image ellipticity')
        else:
            seeing = np.nanmedian(catalog['fwhm'][good_objects]) * pixel_scale
            image[0].header['L1FWHM'] = (seeing, '[arcsec] Frame FWHM in arcsec')
            image[0].header['L1FWTM'] = (np.nanmedian(catalog['fwtm'][good_objects] / catalog['fwhm'][good_objects]),
                                    'Ratio of FWHM to Full-Width Tenth Max')

            mean_ellipticity = stats.sigma_clipped_mean(catalog['ellipticity'][good_objects], 3.0)
            image[0].header['L1ELLIP'] = (mean_ellipticity, 'Mean image ellipticity (1-B/A)')

            mean_position_angle = stats.sigma_clipped_mean(catalog['theta'][good_objects], 3.0)
            image[0].header['L1ELLIPA'] = (mean_position_angle,'[deg] PA of mean image ellipticity')

        

        fits.append(image_file,np.array(catalog))
        with fits.open(image_file, mode='update') as filehandle:
            filehandle[0].header['EXTNAME'] = 'SCI'
            filehandle[1].header['EXTNAME'] = 'CAT'
            
        return image

#image_file = get_pkg_data_filename('lsc1m009-fl03-20151120-0184-e90.fits')
#image = fits.open('lsc1m009-fl03-20151120-0184-e90.fits')
#photometry(image,image_file=image_file,threshold=1.5,min_area=9)

import os
path = '.'
images = [f for f in os.listdir(path) if f.endswith('.fits')]

for i in range(0,(len(images))):
image_file = get_pkg_data_filename(images[i])
image = fits.open(images[i])
photometry(image,image_file=image_file,threshold=1.5,min_area=9)
print(i)
image.close()'

Could you please help me to understand why astrosource doesn't recognize the fits files? Thanks a lot.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions