Example usage - embray/SourceXtractorPlusPlus GitHub Wiki

To run SE++ from my ASDF-support branch, you will first need to run the instructions at: https://github.com/embray/SourceXtractorPlusPlus/wiki/Developing-on-SourceXtractor---in-Conda (or any other means you can get it to build) to make sure you can get SE++ to build and run.

Additional, make sure to:

  1. Clone my fork of the repository ([email protected]:embray/SourceXtractorPlusPlus.git) not the official one
  2. Make sure you have the asdf branch checked out (it should be the default if you git clone directly)

Here we will demonstrate a barebones example of how to run SE++ and test it with ASDF files, as well as provide a bit of documentation for ASDF support works.

Config file

SourceXtractor++ usually runs with a configuration file, though if you don't provide one I believe it can run without. Here is an example config file you can use:

# sepp.conf

# ... skip defaults ... #

# The file to store the output catalog
output-catalog-filename=catalog.txt

# The format of the output catalog, one of ASCII, FITS or FITS_LDAC (default: FITS)
output-catalog-format=ASCII

This is actually almost the same as the default config file that you can output by calling:

$ sourcextractor++ --dump-default-config

with two minor differences:

  1. I set output-catalog-filename=catalog.txt for convenience, but you can also override this at the command-line
  2. I set output-catalog-format=ASCII: The default is FITS which outputs to a FITS table; obviously writing an ASCII file is easier for visual inspection of the output

Generate test "observations"

Here is a trivial Python script that just writes a small "image" with a few single-pixel bright sources, just for test purposes. You could of course make some more realistic test files:

# test_sources.py

import numpy as np
import asdf
from astropy.io import fits

# Create an image with 3 bright spots
image = np.zeros((100, 100), dtype=np.float32)
image[20, 30] = 100.0
image[50, 50] = 200.0
image[70, 80] = 150.0


def make_asdf():
    tree = {
        "science_data": image,
        "meta": {
            "description": "Simple synthetic test image"
        }
    }

    with asdf.AsdfFile(tree) as fobj:
        fobj.write_to('test_image.asdf')


def make_fits():
    hdu = fits.PrimaryHDU(image)
    hdu.writeto("test_image.fits", overwrite=True)


if __name__ == '__main__':
    make_asdf()
    make_fits()

This makes both a FITS file and an ASDF file for the same arrays.

Run

You can run SE++ on these files like:

$ sourcextractor++ --config sepp.conf --detection-image test_image.asdf

If it runs successfully it will output catalog.txt like:

# Column: pixel_centroid_y double (pixel) - Y-position of the object in the detection image

# pixel_centroid_x pixel_centroid_y

                31               21
                51               51
                81               71

You could also try running it on test_image.fits and confirm that it returns the same results.

Using less trivial ASDF files

One complication of ASDF as compared to FITS is that there is not "obvious" way to "find" a detection image in a given ASDF file, as it might be specific to local conventions. Of course, FITS can suffer from this problem as well--ASDF at least allows defining schemas for conventions. But SE++ can't or won't necessarily understand what conventions are in use.

The way it works with FITS files it will just take the first PRIMARY or IMAGE HDU it finds that contains a 2- or 3-dimensional array, of any kind. In fact, if you pass it a multi-extension FITS file with multiple images it will run over all the HDUs unless you specify which one to use (more on that below).

With ASDF files it will do something similar, but it only considers !core/ndarray objects defined at the top level of the YAML tree. So for example if your image is under roman/data it won't be found.

Therefore, the path within the tree under which an image can be found can also be placed in [] after the filename, similar to the IRAF convention for selecting FITS HDUs. For example:

--detection-image=roman_l3.asdf[roman/data]

For a future version it will probably be useful to add a new configuration option for specifying the path or paths under which to find arrays within an ASDF file (not just for images, but other things like weights). It will also be important to be able to specify the paths for WCS data associated with an image.