Source code for galsim.config.extra_truth

# Copyright (c) 2012-2023 by the GalSim developers team on GitHub
# https://github.com/GalSim-developers
#
# This file is part of GalSim: The modular galaxy image simulation toolkit.
# https://github.com/GalSim-developers/GalSim
#
# GalSim is free software: redistribution and use in source and binary forms,
# with or without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions, and the disclaimer given in the accompanying LICENSE
#    file.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions, and the disclaimer given in the documentation
#    and/or other materials provided with the distribution.
#

import sys
import numpy as np
from .extra import ExtraOutputBuilder, RegisterExtraOutput
from .value import ParseValue, GetCurrentValue
from ..errors import GalSimConfigError
from ..catalog import OutputCatalog
from ..utilities import basestring

# The truth extra output type builds an OutputCatalog with truth information about each of the
# objects being built by the configuration processing.  It stores the appropriate row information
# in scratch space for each stamp and then adds them in order at the end of the file processing.
# This means that the stamps can be built out of order by the multiprocessing and still show
# up in the correct order in the output catalog.

# Note that the order of the column names in the output catalog is taken from
# config['output']['truth']['columns'].keys().  So if config is a regular dict, the order
# of the keys is semi-arbitrary.  However, if config is an OrderedDict, the keys come out
# in the order specified.  The standard galsim executable reads the config file into an
# OrderedDict for precisely this reason.

[docs]class TruthBuilder(ExtraOutputBuilder): """Build an output truth catalog with user-defined columns, typically taken from current values of various quantities for each constructed object. """ # The function to call at the end of building each stamp def processStamp(self, obj_num, config, base, logger): cols = config['columns'] row = [] types = [] for name in cols: key = cols[name] if isinstance(key, dict): # Then the "key" is actually something to be parsed in the normal way. # Caveat: We don't know the value_type here, so we give None. This allows # only a limited subset of the parsing. Usually enough for truth items, but # not fully featured. value = ParseValue(cols,name,base,None)[0] elif not isinstance(key,basestring): # The item can just be a constant value. value = key elif key[0] == '$': # This can also be handled by ParseValue value = ParseValue(cols,name,base,None)[0] elif key[0] == '@': # Pop off an initial @ if there is one. value = GetCurrentValue(str(key[1:]), base) else: # str(key) handles the possibility of unicode. In particular, this happens with # JSON files. value = GetCurrentValue(str(key), base) row.append(value) types.append(self._type(value)) if 'types' not in self.scratch: self.scratch['types'] = types elif self.scratch['types'] != types: logger.error("Type mismatch found when building truth catalog at object %d", base['obj_num']) for name, t1, t2 in zip(cols, types, self.scratch['types']): if t1 != t2: logger.error("%s has type %s, but previously had type %s"%( name,t1.__name__,t2.__name__)) raise GalSimConfigError("Type mismatch found when building truth catalog.") self.scratch[obj_num] = row def _type(self, v): if isinstance(v, np.floating): return float elif isinstance(v, np.integer): return int else: return type(v) # The function to call at the end of building each file to finalize the truth catalog def finalize(self, config, base, main_data, logger): # Make the OutputCatalog cols = config['columns'] # Note: Provide a default here, because if all items were skipped it would otherwise # lead to a KeyError. types = self.scratch.pop('types', [float] * len(cols)) cat = OutputCatalog(names=list(cols.keys()), types=types) # Add all the rows in order to the OutputCatalog # Note: types was popped above, so only the obj_num keys are left. obj_nums = sorted(self.scratch.keys()) for obj_num in obj_nums: row = self.scratch[obj_num] cat.addRow(row) return cat # This becomes self.final_data # Write the catalog to a file def writeFile(self, file_name, config, base, logger): self.final_data.write(file_name) # Create an HDU of the FITS binary table. def writeHdu(self, config, base, logger): return self.final_data.writeFitsHdu()
# Register this as a valid extra output RegisterExtraOutput('truth', TruthBuilder())