Making a catalogue object

In order to construct a catalogue, we first require a Catalogue_Creator object which the user needs to create in order to appropriately load in the required data from a .fits catalogue. To load in a catalogue produced by galfind, we make use of the Galfind_Catalogue_Creator class in example 1. In example 2, we will scramble up our previously created JOF catalogue, changing the flux and flux error names, before making a custom Catalogue_Creator object which stores all the same information as in example 1.

[ ]:
# imports
import astropy.units as u
from galfind import Data, Multiple_Filter, Catalogue_Creator, Catalogue
from galfind.Data import morgan_version_to_dir
Reading GALFIND config file from: /nvme/scratch/work/austind/GALFIND/galfind/../configs/galfind_config.ini
WARNING:galfind:Aperture corrections for VISTA not found in /nvme/scratch/work/austind/GALFIND/galfind/Aperture_corrections/VISTA_aper_corr.txt
WARNING:galfind:Aperture corrections for VISTA not found in /nvme/scratch/work/austind/GALFIND/galfind/Aperture_corrections/VISTA_aper_corr.txt
Failed to `import dust_attenuation`
Install from the repo with $ pip install git+https://github.com/karllark/dust_attenuation.git

Example 1: Loading in a galfind catalogue from a Galfind Data object

In this example, we will first produce a Galfind_Catalogue_Creator class before loading in the information stored in the JOF catalogue produced by the Data class in the Data object notebooks. To start with, we shall load a JOF Data object as in previous notebooks.

[ ]:
survey = "JOF"
version = "v11"
instrument_names = ["NIRCam"]
aper_diams = [0.32] * u.arcsec
forced_phot_band = ["F277W", "F356W", "F444W"]
min_flux_pc_err = 10.

JOF_data = Data.pipeline(
    survey,
    version,
    instrument_names = instrument_names,
    version_to_dir_dict = morgan_version_to_dir,
    aper_diams = aper_diams,
    forced_phot_band = forced_phot_band,
    min_flux_pc_err = min_flux_pc_err
)
INFO:galfind:Loaded aper_diams=<Quantity [0.32] arcsec> for F277W+F356W+F444W
INFO:galfind:Combined mask for NIRCam/F277W+F356W+F444W already exists at /raid/scratch/work/austind/GALFIND_WORK/Masks/JOF/combined/JOF_F277W+F356W+F444W_auto.fits
forced_phot_band
phot_cat_path
WARNING: hdu= was not specified but multiple tables are present, reading in first available table (hdu=1) [astropy.io.fits.connect]
WARNING:astroquery:hdu= was not specified but multiple tables are present, reading in first available table (hdu=1)
phot_cat_path
WARNING:galfind:Aperture correction columns already in /raid/scratch/work/austind/GALFIND_WORK/Catalogues/v11/NIRCam/JOF/(0.32)as/JOF_MASTER_Sel-F277W+F356W+F444W_v11.fits
Calculating depths:   0%|          | 0/15 [00:00<?, ?it/s]
INFO:galfind:Calculated/loaded depths for JOF v11 NIRCam
INFO:galfind:Local depth columns already exist in /raid/scratch/work/austind/GALFIND_WORK/Catalogues/v11/NIRCam/JOF/(0.32)as/JOF_MASTER_Sel-F277W+F356W+F444W_v11.fits

Now that we have loaded in the data, we shall create a basic Catalogue_Creator object using the handy from_data classmethod. As per the other galfind classes, we have overloaded the repr and str operators.

[ ]:
cat_creator_1 = Catalogue_Creator.from_data(JOF_data)
repr(cat_creator_1)
print(cat_creator_1)
INFO:galfind:Catalogue cropped by 'ID' to [1]
INFO:galfind:Loaded 'has_data_mask' from /raid/scratch/work/austind/GALFIND_WORK/Masks/JOF/has_data_mask/JOF_MASTER_Sel-F277W+F356W+F444W_v11.h5
INFO:galfind:Making JOF v11 JOF_MASTER_Sel-F277W+F356W+F444W_v11 catalogue!
WARNING:galfind:cat_aper_diams not in kwargs.keys()=dict_keys(['ZP', 'min_flux_pc_err'])! Setting to aper_diams=<Quantity [0.32] arcsec>
WARNING:galfind:cat_aper_diams not in kwargs.keys()=dict_keys(['ZP', 'min_flux_pc_err'])! Setting to aper_diams=<Quantity [0.32] arcsec>
WARNING:galfind:cat_aper_diams not in kwargs.keys()=dict_keys([])! Setting to aper_diams=<Quantity [0.32] arcsec>
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Cell In[3], line 5
      3 aper_diams = [0.32] * u.arcsec
      4 cat_creator = Catalogue_Creator(survey, version, cat_path, filterset, aper_diams, crops = {"ID": 1})
----> 5 cat = cat_creator()
      6 repr(cat)
      7 print(cat)

File /nvme/scratch/work/austind/GALFIND/galfind/Catalogue_Creator.py:298, in Catalogue_Creator.__call__(self, cropped)
    296 filterset_arr = self.load_gal_filtersets(cropped)
    297 SED_results = None
--> 298 assert len(IDs) == len(sky_coords) == len(phot_obs_arr), \
    299     galfind_logger.critical(
    300         f"{len(IDs)=} != {len(sky_coords)=} != {len(phot_obs_arr)=}!"
    301     )
    302 phot_obs_arr = [{aper_diam: Photometry_obs(filterset_arr[i], \
    303     phot[aper_diam][i], phot_err[aper_diam][i], depths[aper_diam][i], \
    304     aper_diam, SED_results=SED_results) for aper_diam in self.aper_diams} \
    305     for i in range(len(filterset_arr))]
    306 # make an array of galaxy objects to be stored in the catalogue

UnboundLocalError: local variable 'phot_obs_arr' referenced before assignment

We see that it is straightforwards to produce a Catalogue object simply by calling the Catalogue_Creator object. By default, the full catalogue is loaded, although we will see in example 3 that this can be updated.

[ ]:
cat_1a = cat_creator_1(cropped = False)
repr(cat_1a)
print(cat_1a)

This catalogue can instead be explicitly created using the Catalogue.pipeline classmethod, done below.

[ ]:
cat_1b = Catalogue.pipeline(
    survey,
    version,
    instrument_names = instrument_names,
    version_to_dir_dict = morgan_version_to_dir,
    aper_diams = aper_diams,
    forced_phot_band = forced_phot_band,
    min_flux_pc_err = min_flux_pc_err
)
# ensure that the two implementations of catalogue loading are the same
if cat_1a == cat_1b:
    print("Catalogue 1a and 1b are the same")
else:
    print("Catalogue 1a and 1b are different")

Example 2: Loading a Galfind Catalogue object explicitly

We note that the implementation in the above example can also be explicitly written instead using Catalogue_Creator.__init__. This init method allows the user to also load in a catalogue created outside of galfind, so long as methods to load in the IDs, sky coordinates, and aperture photometry are given. In addition, if methods to load the depths and SED fitting properties are given, these can be loaded too. The init arguments are extensive and we explicitly write these options below.

[ ]:
# TODO: add more arguments to the __init__ here!
cat_creator_2 = Catalogue_Creator(
    survey,
    version,
    JOF_data.cat_path,
    JOF_data.filterset,
    aper_diams,
)
if cat_creator_1 == cat_creator_2:
    print("Load-in methods are identical")
else:
    print("Load-in methods are not identical")

We see that both the Catalogue_Creator and output cropped/uncropped Catalogue objects using the default arguments are exactly identical to those created by the Catalogue_Creator.from_data() classmethod.

[ ]:
cat_2 = cat_creator_2(cropped = False)
if cat_1a == cat_2:
    print("Uncropped catalogues are identical")
else:
    print("Uncropped catalogues are not identical")

cat_3 = cat_creator_2(cropped = True)
if cat_1a == cat_3:
    print("Cropped catalogues are identical")
else:
    print("Cropped catalogues are not identical")