22__all__ = [
"init_fromDict",
"Functor",
"CompositeFunctor",
"mag_aware_eval",
23 "CustomFunctor",
"Column",
"Index",
"CoordColumn",
"RAColumn",
24 "DecColumn",
"SinglePrecisionFloatColumn",
"HtmIndex20",
"fluxName",
"fluxErrName",
"Mag",
25 "MagErr",
"MagDiff",
"Color",
"DeconvolvedMoments",
"SdssTraceSize",
26 "PsfSdssTraceSizeDiff",
"HsmTraceSize",
"PsfHsmTraceSizeDiff",
27 "HsmFwhm",
"E1",
"E2",
"RadiusFromQuadrupole",
"LocalWcs",
28 "ComputePixelScale",
"ConvertPixelToArcseconds",
29 "ConvertPixelSqToArcsecondsSq",
30 "ConvertDetectorAngleToPositionAngle",
31 "ConvertDetectorAngleErrToPositionAngleErr",
32 "ReferenceBand",
"Photometry",
33 "NanoJansky",
"NanoJanskyErr",
"LocalPhotometry",
"LocalNanojansky",
34 "LocalNanojanskyErr",
"LocalDipoleMeanFlux",
35 "LocalDipoleMeanFluxErr",
"LocalDipoleDiffFlux",
36 "LocalDipoleDiffFluxErr",
"Ebv",
37 "MomentsIuuSky",
"MomentsIvvSky",
"MomentsIuvSky",
38 "CorrelationIuuSky",
"CorrelationIvvSky",
"CorrelationIuvSky",
39 "PositionAngleFromMoments",
"PositionAngleFromCorrelation",
40 "SemimajorAxisFromMoments",
"SemimajorAxisFromCorrelation",
41 "SemiminorAxisFromMoments",
"SemiminorAxisFromCorrelation",
49from contextlib
import redirect_stdout
50from itertools
import product
52import astropy.units
as u
58from astropy.coordinates
import SkyCoord
59from lsst.daf.butler
import DeferredDatasetHandle
60from lsst.pipe.base
import InMemoryDatasetHandle
61from lsst.resources
import ResourcePath
62from lsst.utils
import doImport
63from lsst.utils.introspection
import get_full_type_name
67 typeKey='functor', name=None):
68 """Initialize an object defined in a dictionary.
70 The object needs to be importable as f'{basePath}.{initDict[typeKey]}'.
71 The positional and keyword arguments (if any) are contained in "args" and
72 "kwargs" entries in the dictionary, respectively.
73 This is used in `~lsst.pipe.tasks.functors.CompositeFunctor.from_yaml` to
74 initialize a composite functor from a specification in a YAML file.
79 Dictionary describing object's initialization.
80 Must contain an entry keyed by ``typeKey`` that is the name of the
81 object, relative to ``basePath``.
83 Path relative to module in which ``initDict[typeKey]`` is defined.
85 Key of ``initDict`` that is the name of the object (relative to
88 initDict = initDict.copy()
90 pythonType = doImport(f
'{basePath}.{initDict.pop(typeKey)}')
92 if 'args' in initDict:
93 args = initDict.pop(
'args')
94 if isinstance(args, str):
97 element = pythonType(*args, **initDict)
98 except Exception
as e:
99 message = f
'Error in constructing functor "{name}" of type {pythonType.__name__} with args: {args}'
100 raise type(e)(message, e.args)
105 """Define and execute a calculation on a DataFrame or Handle holding a
108 The `__call__` method accepts either a `~pandas.DataFrame` object or a
109 `~lsst.daf.butler.DeferredDatasetHandle` or
110 `~lsst.pipe.base.InMemoryDatasetHandle`, and returns the
111 result of the calculation as a single column.
112 Each functor defines what columns are needed for the calculation, and only
113 these columns are read from the dataset handle.
115 The action of `__call__` consists of two steps: first, loading the
116 necessary columns from disk into memory as a `~pandas.DataFrame` object;
117 and second, performing the computation on this DataFrame and returning the
120 To define a new `Functor`, a subclass must define a `_func` method,
121 that takes a `~pandas.DataFrame` and returns result in a `~pandas.Series`.
122 In addition, it must define the following attributes:
124 * `_columns`: The columns necessary to perform the calculation
125 * `name`: A name appropriate for a figure axis label
126 * `shortname`: A name appropriate for use as a dictionary key
128 On initialization, a `Functor` should declare what band (``filt`` kwarg)
129 and dataset (e.g. ``'ref'``, ``'meas'``, ``'forced_src'``) it is intended
131 This enables the `_get_data` method to extract the proper columns from the
133 If not specified, the dataset will fall back on the `_defaultDataset`
135 If band is not specified and ``dataset`` is anything other than ``'ref'``,
136 then an error will be raised when trying to perform the calculation.
138 Originally, `Functor` was set up to expect datasets formatted like the
139 ``deepCoadd_obj`` dataset; that is, a DataFrame with a multi-level column
140 index, with the levels of the column index being ``band``, ``dataset``, and
142 It has since been generalized to apply to DataFrames without multi-level
143 indices and multi-level indices with just ``dataset`` and ``column``
145 In addition, the `_get_data` method that reads the columns from the
146 underlying data will return a DataFrame with column index levels defined by
147 the `_dfLevels` attribute; by default, this is ``column``.
149 The `_dfLevels` attributes should generally not need to be changed, unless
150 `_func` needs columns from multiple filters or datasets to do the
152 An example of this is the `~lsst.pipe.tasks.functors.Color` functor, for
153 which `_dfLevels = ('band', 'column')`, and `_func` expects the DataFrame
154 it gets to have those levels in the column index.
159 Band upon which to do the calculation.
162 Dataset upon which to do the calculation (e.g., 'ref', 'meas',
166 _defaultDataset =
'ref'
167 _dfLevels = (
'column',)
168 _defaultNoDup =
False
170 def __init__(self, filt=None, dataset=None, noDup=None):
174 self.
log = logging.getLogger(type(self).__name__)
178 """Do not explode by band if used on object table."""
179 if self.
_noDup is not None:
186 """Columns required to perform calculation."""
187 if not hasattr(self,
'_columns'):
188 raise NotImplementedError(
'Must define columns property or _columns attribute')
192 """Gets the names of the column index levels.
194 This should only be called in the context of a multilevel table.
199 The data to be read, can be a
200 `~lsst.daf.butler.DeferredDatasetHandle` or
201 `~lsst.pipe.base.InMemoryDatasetHandle`.
202 columnIndex (optional): pandas `~pandas.Index` object
203 If not passed, then it is read from the
204 `~lsst.daf.butler.DeferredDatasetHandle`
205 for `~lsst.pipe.base.InMemoryDatasetHandle`.
207 if columnIndex
is None:
208 columnIndex = data.get(component=
"columns")
209 return columnIndex.names
212 """Gets the content of each of the column levels for a multilevel
215 if columnIndex
is None:
216 columnIndex = data.get(component=
"columns")
218 columnLevels = columnIndex.names
220 level: list(np.unique(np.array([c
for c
in columnIndex])[:, i]))
221 for i, level
in enumerate(columnLevels)
223 return columnLevelNames
226 """Converts dictionary column specficiation to a list of columns."""
230 for i, lev
in enumerate(columnLevels):
232 if isinstance(colDict[lev], str):
233 new_colDict[lev] = [colDict[lev]]
235 new_colDict[lev] = colDict[lev]
237 new_colDict[lev] = columnIndex.levels[i]
239 levelCols = [new_colDict[lev]
for lev
in columnLevels]
240 cols = list(product(*levelCols))
241 colsAvailable = [col
for col
in cols
if col
in columnIndex]
245 """Returns columns needed by functor from multilevel dataset.
247 To access tables with multilevel column structure, the
248 `~lsst.daf.butler.DeferredDatasetHandle` or
249 `~lsst.pipe.base.InMemoryDatasetHandle` needs to be passed
250 either a list of tuples or a dictionary.
255 The data as either `~lsst.daf.butler.DeferredDatasetHandle`, or
256 `~lsst.pipe.base.InMemoryDatasetHandle`.
257 columnIndex (optional): pandas `~pandas.Index` object
258 Either passed or read in from
259 `~lsst.daf.butler.DeferredDatasetHandle`.
260 `returnTuple` : `bool`
261 If true, then return a list of tuples rather than the column
262 dictionary specification.
263 This is set to `True` by `CompositeFunctor` in order to be able to
264 combine columns from the various component functors.
267 if not isinstance(data, (DeferredDatasetHandle, InMemoryDatasetHandle)):
268 raise RuntimeError(f
"Unexpected data type. Got {get_full_type_name(data)}.")
270 if columnIndex
is None:
271 columnIndex = data.get(component=
"columns")
277 columnDict = {
'column': self.
columns,
279 if self.
filt is None:
281 if "band" in columnLevels:
283 columnDict[
"band"] = columnLevelNames[
"band"][0]
285 raise ValueError(f
"'filt' not set for functor {self.name}"
286 f
"(dataset {self.dataset}) "
288 "contains multiple filters in column index. "
289 "Set 'filt' or set 'dataset' to 'ref'.")
291 columnDict[
'band'] = self.
filt
294 return self.
_colsFromDict(columnDict, columnIndex=columnIndex)
299 raise NotImplementedError(
'Must define calculation on DataFrame')
302 """Return columnIndex."""
304 if isinstance(data, (DeferredDatasetHandle, InMemoryDatasetHandle)):
305 return data.get(component=
"columns")
310 """Retrieve DataFrame necessary for calculation.
312 The data argument can be a `~pandas.DataFrame`, a
313 `~lsst.daf.butler.DeferredDatasetHandle`, or
314 an `~lsst.pipe.base.InMemoryDatasetHandle`.
316 Returns a DataFrame upon which `self._func` can act.
320 if isinstance(data, pd.DataFrame):
321 _data = InMemoryDatasetHandle(data, storageClass=
"DataFrame")
322 elif isinstance(data, (DeferredDatasetHandle, InMemoryDatasetHandle)):
325 raise RuntimeError(f
"Unexpected type provided for data. Got {get_full_type_name(data)}.")
330 is_multiLevel = isinstance(columnIndex, pd.MultiIndex)
339 df = _data.get(parameters={
"columns": columns})
348 levelsToDrop = [n
for n
in df.columns.names
if n
not in self.
_dfLevels]
349 df.columns = df.columns.droplevel(levelsToDrop)
358 vals = self.
_func(df)
359 except Exception
as e:
360 self.
log.error(
"Exception in %s call: %s: %s", self.
name, type(e).__name__, e)
368 """Computes difference between functor called on two different
369 DataFrame/Handle objects.
371 return self(data1, **kwargs) -
self(data2, **kwargs)
374 return pd.Series(np.full(len(df), np.nan), index=df.index)
378 """Full name of functor (suitable for figure labels)."""
379 return NotImplementedError
383 """Short name of functor (suitable for column name/dict key)."""
388 """Perform multiple calculations at once on a catalog.
390 The role of a `CompositeFunctor` is to group together computations from
392 Instead of returning `~pandas.Series` a `CompositeFunctor` returns a
393 `~pandas.DataFrame`, with the column names being the keys of ``funcDict``.
395 The `columns` attribute of a `CompositeFunctor` is the union of all columns
396 in all the component functors.
398 A `CompositeFunctor` does not use a `_func` method itself; rather, when a
399 `CompositeFunctor` is called, all its columns are loaded at once, and the
400 resulting DataFrame is passed to the `_func` method of each component
402 This has the advantage of only doing I/O (reading from parquet file) once,
403 and works because each individual `_func` method of each component functor
404 does not care if there are *extra* columns in the DataFrame being passed;
405 only that it must contain *at least* the `columns` it expects.
407 An important and useful class method is `from_yaml`, which takes as an
408 argument the path to a YAML file specifying a collection of functors.
412 funcs : `dict` or `list`
413 Dictionary or list of functors.
414 If a list, then it will be converted into a dictonary according to the
415 `.shortname` attribute of each functor.
418 name =
"CompositeFunctor"
422 if type(funcs)
is dict:
425 self.
funcDict = {f.shortname: f
for f
in funcs}
443 """Update the functor with new functors."""
444 if isinstance(new, dict):
446 elif isinstance(new, CompositeFunctor):
449 raise TypeError(
'Can only update with dictionary or CompositeFunctor.')
452 if self.
filt is not None:
457 return list(set([x
for y
in [f.columns
for f
in self.
funcDict.values()]
for x
in y]))
467 f.multilevelColumns(data, returnTuple=
True, **kwargs)
for f
in self.
funcDict.values()
475 """Apply the functor to the data table.
480 The data represented as `~lsst.daf.butler.DeferredDatasetHandle`,
481 `~lsst.pipe.base.InMemoryDatasetHandle`, or `~pandas.DataFrame`.
482 The table or a pointer to a table on disk from which columns can
485 if isinstance(data, pd.DataFrame):
486 _data = InMemoryDatasetHandle(data, storageClass=
"DataFrame")
487 elif isinstance(data, (DeferredDatasetHandle, InMemoryDatasetHandle)):
490 raise RuntimeError(f
"Unexpected type provided for data. Got {get_full_type_name(data)}.")
494 if isinstance(columnIndex, pd.MultiIndex):
496 df = _data.get(parameters={
"columns": columns})
501 subdf = f._setLevels(
502 df[f.multilevelColumns(_data, returnTuple=
True, columnIndex=columnIndex)]
504 valDict[k] = f._func(subdf)
505 except Exception
as e:
507 "Exception in %s (funcs: %s) call: %s",
513 valDict[k] = f.fail(subdf)
518 df = _data.get(parameters={
"columns": self.
columns})
520 valDict = {k: f._func(df)
for k, f
in self.
funcDict.items()}
523 for name, colVal
in valDict.items():
524 if len(colVal.shape) != 1:
525 raise RuntimeError(
"Transformed column '%s' is not the shape of a column. "
526 "It is shaped %s and type %s." % (name, colVal.shape, type(colVal)))
529 valDf = pd.concat(valDict, axis=1)
531 print([(k, type(v))
for k, v
in valDict.items()])
534 if kwargs.get(
'dropna',
False):
535 valDf = valDf.dropna(how=
'any')
541 if renameRules
is None:
543 for old, new
in renameRules:
544 if col.startswith(old):
545 col = col.replace(old, new)
551 filename = os.path.expandvars(filename)
552 with ResourcePath(filename).open(
"r")
as f:
553 translationDefinition = yaml.safe_load(f)
555 return cls.
from_yaml(translationDefinition, **kwargs)
560 for func, val
in translationDefinition[
'funcs'].items():
563 if 'flag_rename_rules' in translationDefinition:
564 renameRules = translationDefinition[
'flag_rename_rules']
568 if 'calexpFlags' in translationDefinition:
569 for flag
in translationDefinition[
'calexpFlags']:
570 funcs[cls.
renameCol(flag, renameRules)] =
Column(flag, dataset=
'calexp')
572 if 'refFlags' in translationDefinition:
573 for flag
in translationDefinition[
'refFlags']:
576 if 'forcedFlags' in translationDefinition:
577 for flag
in translationDefinition[
'forcedFlags']:
578 funcs[cls.
renameCol(flag, renameRules)] =
Column(flag, dataset=
'forced_src')
580 if 'flags' in translationDefinition:
581 for flag
in translationDefinition[
'flags']:
584 return cls(funcs, **kwargs)
588 """Evaluate an expression on a DataFrame, knowing what the 'mag' function
591 Builds on `pandas.DataFrame.eval`, which parses and executes math on
596 df : ~pandas.DataFrame
597 DataFrame on which to evaluate expression.
603 expr_new = re.sub(
r'mag\((\w+)\)',
r'-2.5*log(\g<1>)/log(10)', expr)
604 val = df.eval(expr_new)
605 except Exception
as e:
606 log.error(
"Exception in mag_aware_eval: %s: %s", type(e).__name__, e)
607 expr_new = re.sub(
r'mag\((\w+)\)',
r'-2.5*log(\g<1>_instFlux)/log(10)', expr)
608 val = df.eval(expr_new)
613 """Arbitrary computation on a catalog.
615 Column names (and thus the columns to be loaded from catalog) are found by
616 finding all words and trying to ignore all "math-y" words.
621 Expression to evaluate, to be parsed and executed by
622 `~lsst.pipe.tasks.functors.mag_aware_eval`.
624 _ignore_words = (
'mag',
'sin',
'cos',
'exp',
'log',
'sqrt')
636 flux_cols = re.findall(
r'mag\(\s*(\w+)\s*\)', self.
expr)
638 cols = [c
for c
in re.findall(
r'[a-zA-Z_]+', self.
expr)
if c
not in self.
_ignore_words]
641 if not re.search(
'_instFlux$', c):
642 cols.append(f
'{c}_instFlux')
647 return list(set([c
for c
in cols
if c
not in not_a_col]))
654 """Get column with a specified name."""
673 """Return the value of the index for each object."""
675 columns = [
'coord_ra']
676 _defaultDataset =
'ref'
680 return pd.Series(df.index, index=df.index)
684 """Base class for coordinate column, in degrees."""
693 output = df[self.
col] * 180 / np.pi
if self.
_radians else df[self.
col]
698 """Right Ascension, in degrees."""
703 super().
__init__(
'coord_ra', **kwargs)
706 return super().
__call__(catalog, **kwargs)
710 """Declination, in degrees."""
715 super().
__init__(
'coord_dec', **kwargs)
718 return super().
__call__(catalog, **kwargs)
722 """Angular uncertainty in Right Ascension, in degrees.
724 Note that ``coord_raErr`` is the uncertainty on RA·cos(Dec),
725 i.e. an arc-length on the sky in the RA direction.
731 super().
__init__(
'coord_raErr', **kwargs)
735 """Uncertainty in declination, in degrees."""
740 super().
__init__(
'coord_decErr', **kwargs)
744 """Tangent-plane angular covariance, in degrees^2.
746 As with the RA error, this is the covariance between RA·cos(Dec) and Dec,
747 Cov(xi, eta) = Cov(RA*cos(Dec), Dec).
754 super().
__init__(
'coord_ra_dec_Cov', **kwargs)
759 output = df[self.
col]*(180/np.pi)**2
if self.
_radians else df[self.
col]
764 """A column with a band in a multiband table."""
775 """A float32 MultibandColumn"""
777 return super().
_func(df).astype(np.float32)
781 """Return a column cast to a single-precision float."""
784 return df[self.
col].astype(np.float32)
788 """Compute the level 20 HtmIndex for the catalog.
792 This functor was implemented to satisfy requirements of old APDB interface
793 which required the ``pixelId`` column in DiaObject with HTM20 index.
794 The APDB interface had migrated to not need that information, but we keep
795 this class in case it may be useful for something else.
810 def computePixel(row):
819 return self.
pixelator.index(sphPoint.getVector())
821 return df.apply(computePixel, axis=1, result_type=
'reduce').astype(
'int64')
825 """Append _instFlux to the column name if it doesn't have it already."""
826 if not col.endswith(
'_instFlux'):
832 """Append _instFluxErr to the column name if it doesn't have it already."""
833 if not col.endswith(
'_instFluxErr'):
834 col +=
'_instFluxErr'
839 """Compute calibrated magnitude.
841 Returns the flux at mag=0.
842 The default ``fluxMag0`` is 63095734448.0194, which is default for HSC.
843 TO DO: This default should be made configurable in DM-21955.
845 This calculation hides warnings about invalid values and dividing by zero.
847 As with all functors, a ``dataset`` and ``filt`` kwarg should be provided
849 Unlike the default `Functor`, however, the default dataset for a `Mag` is
850 ``'meas'``, rather than ``'ref'``.
855 Name of flux column from which to compute magnitude.
856 Can be parseable by the `~lsst.pipe.tasks.functors.fluxName` function;
857 that is, you can pass ``'modelfit_CModel'`` instead of
858 ``'modelfit_CModel_instFlux'``, and it will understand.
860 _defaultDataset =
'meas'
874 with warnings.catch_warnings():
875 warnings.filterwarnings(
'ignore',
r'invalid value encountered')
876 warnings.filterwarnings(
'ignore',
r'divide by zero')
881 return f
'mag_{self.col}'
885 """Compute calibrated magnitude uncertainty.
890 Name of the flux column.
903 with warnings.catch_warnings():
904 warnings.filterwarnings(
'ignore',
r'invalid value encountered')
905 warnings.filterwarnings(
'ignore',
r'divide by zero')
906 fluxCol, fluxErrCol = self.
columns
907 x = df[fluxErrCol] / df[fluxCol]
909 magErr = (2.5 / np.log(10.)) * np.sqrt(x*x + y*y)
914 return super().name +
'_err'
918 """Functor to calculate magnitude difference."""
919 _defaultDataset =
'meas'
931 with warnings.catch_warnings():
932 warnings.filterwarnings(
'ignore',
r'invalid value encountered')
933 warnings.filterwarnings(
'ignore',
r'divide by zero')
934 return -2.5*np.log10(df[self.
col1]/df[self.
col2])
938 return f
'(mag_{self.col1} - mag_{self.col2})'
942 return f
'magDiff_{self.col1}_{self.col2}'
946 """Compute the color between two filters.
948 Computes color by initializing two different `Mag` functors based on the
949 ``col`` and filters provided, and then returning the difference.
951 This is enabled by the `_func` method expecting a DataFrame with a
952 multilevel column index, with both ``'band'`` and ``'column'``, instead of
953 just ``'column'``, which is the `Functor` default.
954 This is controlled by the `_dfLevels` attribute.
956 Also of note, the default dataset for `Color` is ``forced_src'``, whereas
957 for `Mag` it is ``'meas'``.
962 Name of the flux column from which to compute; same as would be passed
963 to `~lsst.pipe.tasks.functors.Mag`.
966 Filters from which to compute magnitude difference.
967 Color computed is ``Mag(filt2) - Mag(filt1)``.
969 _defaultDataset =
'forced_src'
970 _dfLevels = (
'band',
'column')
976 raise RuntimeError(
"Cannot compute Color for %s: %s - %s " % (col, filt2, filt1))
994 mag2 = self.mag2.
_func(df[self.filt2])
995 mag1 = self.mag1.
_func(df[self.filt1])
1000 return [self.
mag1.col, self.
mag2.col]
1007 return f
'{self.filt2} - {self.filt1} ({self.col})'
1011 return f
"{self.col}_{self.filt2.replace('-', '')}m{self.filt1.replace('-', '')}"
1015 """This functor subtracts the trace of the PSF second moments from the
1016 trace of the second moments of the source.
1018 If the HsmShapeAlgorithm measurement is valid, then these will be used for
1020 Otherwise, the SdssShapeAlgorithm measurements will be used.
1022 name =
'Deconvolved Moments'
1023 shortname =
'deconvolvedMoments'
1024 _columns = (
"ext_shapeHSM_HsmSourceMoments_xx",
1025 "ext_shapeHSM_HsmSourceMoments_yy",
1026 "base_SdssShape_xx",
"base_SdssShape_yy",
1027 "ext_shapeHSM_HsmPsfMoments_xx",
1028 "ext_shapeHSM_HsmPsfMoments_yy")
1031 """Calculate deconvolved moments."""
1032 if "ext_shapeHSM_HsmSourceMoments_xx" in df.columns:
1033 hsm = df[
"ext_shapeHSM_HsmSourceMoments_xx"] + df[
"ext_shapeHSM_HsmSourceMoments_yy"]
1035 hsm = np.ones(len(df))*np.nan
1036 sdss = df[
"base_SdssShape_xx"] + df[
"base_SdssShape_yy"]
1037 if "ext_shapeHSM_HsmPsfMoments_xx" in df.columns:
1038 psf = df[
"ext_shapeHSM_HsmPsfMoments_xx"] + df[
"ext_shapeHSM_HsmPsfMoments_yy"]
1043 raise RuntimeError(
'No psf shape parameter found in catalog')
1045 return hsm.where(np.isfinite(hsm), sdss) - psf
1049 """Functor to calculate the SDSS trace radius size for sources.
1051 The SDSS trace radius size is a measure of size equal to the square root of
1052 half of the trace of the second moments tensor measured with the
1053 SdssShapeAlgorithm plugin.
1054 This has units of pixels.
1056 name =
"SDSS Trace Size"
1057 shortname =
'sdssTrace'
1058 _columns = (
"base_SdssShape_xx",
"base_SdssShape_yy")
1061 srcSize = np.sqrt(0.5*(df[
"base_SdssShape_xx"] + df[
"base_SdssShape_yy"]))
1066 """Functor to calculate the SDSS trace radius size difference (%) between
1067 the object and the PSF model.
1073 name =
"PSF - SDSS Trace Size"
1074 shortname =
'psf_sdssTrace'
1075 _columns = (
"base_SdssShape_xx",
"base_SdssShape_yy",
1076 "base_SdssShape_psf_xx",
"base_SdssShape_psf_yy")
1079 srcSize = np.sqrt(0.5*(df[
"base_SdssShape_xx"] + df[
"base_SdssShape_yy"]))
1080 psfSize = np.sqrt(0.5*(df[
"base_SdssShape_psf_xx"] + df[
"base_SdssShape_psf_yy"]))
1081 sizeDiff = 100*(srcSize - psfSize)/(0.5*(srcSize + psfSize))
1086 """Functor to calculate the HSM trace radius size for sources.
1088 The HSM trace radius size is a measure of size equal to the square root of
1089 half of the trace of the second moments tensor measured with the
1090 HsmShapeAlgorithm plugin.
1091 This has units of pixels.
1093 name =
'HSM Trace Size'
1094 shortname =
'hsmTrace'
1095 _columns = (
"ext_shapeHSM_HsmSourceMoments_xx",
1096 "ext_shapeHSM_HsmSourceMoments_yy")
1099 srcSize = np.sqrt(0.5*(df[
"ext_shapeHSM_HsmSourceMoments_xx"]
1100 + df[
"ext_shapeHSM_HsmSourceMoments_yy"]))
1105 """Functor to calculate the HSM trace radius size difference (%) between
1106 the object and the PSF model.
1112 name =
'PSF - HSM Trace Size'
1113 shortname =
'psf_HsmTrace'
1114 _columns = (
"ext_shapeHSM_HsmSourceMoments_xx",
1115 "ext_shapeHSM_HsmSourceMoments_yy",
1116 "ext_shapeHSM_HsmPsfMoments_xx",
1117 "ext_shapeHSM_HsmPsfMoments_yy")
1120 srcSize = np.sqrt(0.5*(df[
"ext_shapeHSM_HsmSourceMoments_xx"]
1121 + df[
"ext_shapeHSM_HsmSourceMoments_yy"]))
1122 psfSize = np.sqrt(0.5*(df[
"ext_shapeHSM_HsmPsfMoments_xx"]
1123 + df[
"ext_shapeHSM_HsmPsfMoments_yy"]))
1124 sizeDiff = 100*(srcSize - psfSize)/(0.5*(srcSize + psfSize))
1129 """Functor to calculate the PSF FWHM with second moments measured from the
1130 HsmShapeAlgorithm plugin.
1132 This is in units of arcseconds, and assumes the hsc_rings_v1 skymap pixel
1133 scale of 0.168 arcseconds/pixel.
1137 This conversion assumes the PSF is Gaussian, which is not always the case.
1139 name =
'HSM Psf FWHM'
1140 _columns = (
'ext_shapeHSM_HsmPsfMoments_xx',
'ext_shapeHSM_HsmPsfMoments_yy')
1143 SIGMA2FWHM = 2*np.sqrt(2*np.log(2))
1147 0.5*(df[
'ext_shapeHSM_HsmPsfMoments_xx']
1148 + df[
'ext_shapeHSM_HsmPsfMoments_yy']))).astype(np.float32)
1152 r"""Calculate :math:`e_1` ellipticity component for sources, defined as:
1155 e_1 &= (I_{xx}-I_{yy})/(I_{xx}+I_{yy})
1161 name =
"Distortion Ellipticity (e1)"
1162 shortname =
"Distortion"
1176 return ((df[self.
colXX] - df[self.
colYY]) / (
1177 df[self.
colXX] + df[self.
colYY])).astype(np.float32)
1181 r"""Calculate :math:`e_2` ellipticity component for sources, defined as:
1184 e_2 &= 2I_{xy}/(I_{xx}+I_{yy})
1190 name =
"Ellipticity e2"
1203 return (2*df[self.
colXY] / (df[self.
colXX] + df[self.
colYY])).astype(np.float32)
1207 """Calculate the radius from the quadrupole moments.
1209 This returns the fourth root of the determinant of the second moments
1210 tensor, which has units of pixels.
1229 return ((df[self.
colXX]*df[self.
colYY] - df[self.
colXY]**2)**0.25).astype(np.float32)
1233 """Computations using the stored localWcs."""
1234 name =
"LocalWcsOperations"
1249 """Compute the dRA, dDec from dx, dy.
1253 x : `~pandas.Series`
1255 y : `~pandas.Series`
1257 cd11 : `~pandas.Series`
1258 [1, 1] element of the local Wcs affine transform.
1259 cd12 : `~pandas.Series`
1260 [1, 2] element of the local Wcs affine transform.
1261 cd21 : `~pandas.Series`
1262 [2, 1] element of the local Wcs affine transform.
1263 cd22 : `~pandas.Series`
1264 [2, 2] element of the local Wcs affine transform.
1269 RA and Dec conversion of x and y given the local Wcs.
1270 Returned units are in radians.
1274 If x and y are with respect to the CRVAL1, CRVAL2
1275 then this will return the RA, Dec for that WCS.
1277 return (x * cd11 + y * cd12, x * cd21 + y * cd22)
1280 """Compute the local pixel scale conversion.
1284 ra1 : `~pandas.Series`
1285 Ra of the first coordinate in radians.
1286 dec1 : `~pandas.Series`
1287 Dec of the first coordinate in radians.
1288 ra2 : `~pandas.Series`
1289 Ra of the second coordinate in radians.
1290 dec2 : `~pandas.Series`
1291 Dec of the second coordinate in radians.
1295 dist : `~pandas.Series`
1296 Distance on the sphere in radians.
1298 deltaDec = dec2 - dec1
1300 return 2 * np.arcsin(
1302 np.sin(deltaDec / 2) ** 2
1303 + np.cos(dec2) * np.cos(dec1) * np.sin(deltaRa / 2) ** 2))
1306 """Compute the distance on the sphere from x2, y1 to x1, y1.
1310 x1 : `~pandas.Series`
1312 y1 : `~pandas.Series`
1314 x2 : `~pandas.Series`
1316 y2 : `~pandas.Series`
1318 cd11 : `~pandas.Series`
1319 [1, 1] element of the local Wcs affine transform.
1320 cd12 : `~pandas.Series`
1321 [1, 2] element of the local Wcs affine transform.
1322 cd21 : `~pandas.Series`
1323 [2, 1] element of the local Wcs affine transform.
1324 cd22 : `~pandas.Series`
1325 [2, 2] element of the local Wcs affine transform.
1329 Distance : `~pandas.Series`
1330 Arcseconds per pixel at the location of the local WC.
1338 """Compute position angle (E of N) from (ra1, dec1) to (ra2, dec2).
1342 ra1 : iterable [`float`]
1343 RA of the first coordinate [radian].
1344 dec1 : iterable [`float`]
1345 Dec of the first coordinate [radian].
1346 ra2 : iterable [`float`]
1347 RA of the second coordinate [radian].
1348 dec2 : iterable [`float`]
1349 Dec of the second coordinate [radian].
1353 Position Angle: `~pandas.Series`
1358 (ra1, dec1) -> (ra2, dec2) is interpreted as the shorter way around the sphere
1360 For a separation of 0.0001 rad, the position angle is good to 0.0009 rad
1361 all over the sphere.
1365 position_angle = np.zeros(len(ra1))
1366 for i, (r1, d1, r2, d2)
in enumerate(zip(ra1, dec1, ra2, dec2)):
1369 bearing = point1.bearingTo(point2)
1370 pa_ref_angle =
geom.Angle(np.pi/2, geom.radians)
1371 pa = pa_ref_angle - bearing
1374 position_angle[i] = pa.asRadians()
1376 return pd.Series(position_angle)
1379 """Compute position angle (E of N) from detector angle (+y of +x).
1384 detector angle [radian]
1386 [1, 1] element of the local Wcs affine transform.
1388 [1, 2] element of the local Wcs affine transform.
1390 [2, 1] element of the local Wcs affine transform.
1392 [2, 2] element of the local Wcs affine transform.
1396 Position Angle: `~pandas.Series`
1409 """Compute the local pixel scale from the stored CDMatrix.
1421 """Compute the local pixel to scale conversion in arcseconds.
1425 cd11 : `~pandas.Series`
1426 [1, 1] element of the local Wcs affine transform in radians.
1427 cd11 : `~pandas.Series`
1428 [1, 1] element of the local Wcs affine transform in radians.
1429 cd12 : `~pandas.Series`
1430 [1, 2] element of the local Wcs affine transform in radians.
1431 cd21 : `~pandas.Series`
1432 [2, 1] element of the local Wcs affine transform in radians.
1433 cd22 : `~pandas.Series`
1434 [2, 2] element of the local Wcs affine transform in radians.
1438 pixScale : `~pandas.Series`
1439 Arcseconds per pixel at the location of the local WC.
1441 return 3600 * np.degrees(np.sqrt(np.fabs(cd11 * cd22 - cd12 * cd21)))
1451 """Convert a value in units of pixels to units of arcseconds."""
1469 return f
"{self.col}_asArcseconds"
1487 """Convert a value in units of pixels squared to units of arcseconds
1507 return f
"{self.col}_asArcsecondsSq"
1522 return df[self.
col] * pixScale * pixScale
1526 """Compute a position angle from a detector angle and the stored CDMatrix.
1530 position angle : degrees
1533 name =
"PositionAngle"
1545 super().
__init__(colCD_1_1, colCD_1_2, colCD_2_1, colCD_2_2, **kwargs)
1568 """Convert a detector angle error to a position angle error.
1572 position angle error : degrees
1575 name =
"PositionAngleErr"
1590 """Return the band used to seed multiband forced photometry.
1592 This functor is to be used on Object tables.
1593 It converts the boolean merge_measurements_{band} columns into a single
1594 string representing the first band for which merge_measurements_{band}
1597 Assumes the default priority order of i, r, z, y, g, u.
1599 name =
'Reference Band'
1600 shortname =
'refBand'
1602 band_order = (
"i",
"r",
"z",
"y",
"g",
"u")
1610 return [f
"merge_measurement_{band}" for band
in bands]
1612 def _func(self, df: pd.DataFrame) -> pd.Series:
1613 def getFilterAliasName(row):
1615 colName = row.idxmax()
1616 return colName.replace(
'merge_measurement_',
'')
1620 columns = [col
for col
in self.
columns if col
in df.columns]
1622 return df[columns].apply(getFilterAliasName, axis=1,
1623 result_type=
'reduce').astype(
'object')
1625 def __init__(self, bands: tuple[str] | list[str] |
None =
None, **kwargs):
1631 """Base class for Object table calibrated fluxes and magnitudes."""
1633 AB_FLUX_SCALE = (0 * u.ABmag).to_value(u.nJy)
1634 LOG_AB_FLUX_SCALE = 12.56
1635 FIVE_OVER_2LOG10 = 1.085736204758129569
1639 def __init__(self, colFlux, colFluxErr=None, **kwargs):
1655 return f
'mag_{self.col}'
1659 """Compute sqrt(a^2 + b^2) without under/overflow."""
1660 if np.abs(a) < np.abs(b):
1665 return np.abs(a) * np.sqrt(1. + q*q)
1668 """Convert instrumental flux to nanojanskys."""
1669 return (self.
AB_FLUX_SCALE * dn / fluxMag0).astype(np.float32)
1672 """Convert instrumental flux to AB magnitude."""
1673 with warnings.catch_warnings():
1674 warnings.filterwarnings(
'ignore',
r'invalid value encountered')
1675 warnings.filterwarnings(
'ignore',
r'divide by zero')
1676 return (-2.5 * np.log10(dn/fluxMag0)).astype(np.float32)
1679 """Convert instrumental flux error to nanojanskys."""
1680 retVal = self.
vhypot(dn * fluxMag0Err, dnErr * fluxMag0)
1682 return retVal.astype(np.float32)
1685 """Convert instrumental flux error to AB magnitude error."""
1686 retVal = self.
dn2fluxErr(dn, dnErr, fluxMag0, fluxMag0Err) / self.
dn2flux(dn, fluxMag0)
1691 """Convert instrumental flux to nanojanskys."""
1697 """Convert instrumental flux error to nanojanskys."""
1704 return pd.Series(retArr, index=df.index)
1708 """Base class for calibrating the specified instrument flux column using
1709 the local photometric calibration.
1714 Name of the instrument flux column.
1715 instFluxErrCol : `str`
1716 Name of the assocated error columns for ``instFluxCol``.
1717 photoCalibCol : `str`
1718 Name of local calibration column.
1719 photoCalibErrCol : `str`, optional
1720 Error associated with ``photoCalibCol``. Ignored and deprecated; will
1721 be removed after v29.
1728 logNJanskyToAB = (1 * u.nJy).to_value(u.ABmag)
1734 photoCalibErrCol=None,
1740 if photoCalibErrCol
is not None:
1741 warnings.warn(
"The photoCalibErrCol argument is deprecated and will be removed after v29.",
1742 category=FutureWarning)
1746 """Convert instrument flux to nanojanskys.
1750 instFlux : `~numpy.ndarray` or `~pandas.Series`
1751 Array of instrument flux measurements.
1752 localCalib : `~numpy.ndarray` or `~pandas.Series`
1753 Array of local photometric calibration estimates.
1757 calibFlux : `~numpy.ndarray` or `~pandas.Series`
1758 Array of calibrated flux measurements.
1760 return instFlux * localCalib
1763 """Convert instrument flux to nanojanskys.
1767 instFlux : `~numpy.ndarray` or `~pandas.Series`
1768 Array of instrument flux measurements. Ignored (accepted for
1769 backwards compatibility and consistency with magnitude-error
1770 calculation methods).
1771 instFluxErr : `~numpy.ndarray` or `~pandas.Series`
1772 Errors on associated ``instFlux`` values.
1773 localCalib : `~numpy.ndarray` or `~pandas.Series`
1774 Array of local photometric calibration estimates.
1775 localCalibErr : `~numpy.ndarray` or `~pandas.Series`, optional
1776 Errors on associated ``localCalib`` values. Ignored and deprecated;
1777 will be removed after v29.
1781 calibFluxErr : `~numpy.ndarray` or `~pandas.Series`
1782 Errors on calibrated flux measurements.
1785 if localCalibErr
is not None:
1786 warnings.warn(
"The localCalibErr argument is deprecated and will be removed after v29.",
1787 category=FutureWarning)
1788 return instFluxErr * localCalib
1791 """Convert instrument flux to nanojanskys.
1795 instFlux : `~numpy.ndarray` or `~pandas.Series`
1796 Array of instrument flux measurements.
1797 localCalib : `~numpy.ndarray` or `~pandas.Series`
1798 Array of local photometric calibration estimates.
1802 calibMag : `~numpy.ndarray` or `~pandas.Series`
1803 Array of calibrated AB magnitudes.
1808 """Convert instrument flux err to nanojanskys.
1812 instFlux : `~numpy.ndarray` or `~pandas.Series`
1813 Array of instrument flux measurements.
1814 instFluxErr : `~numpy.ndarray` or `~pandas.Series`
1815 Errors on associated ``instFlux`` values.
1816 localCalib : `~numpy.ndarray` or `~pandas.Series`
1817 Array of local photometric calibration estimates.
1818 localCalibErr : `~numpy.ndarray` or `~pandas.Series`, optional
1819 Errors on associated ``localCalib`` values. Ignored and deprecated;
1820 will be removed after v29.
1824 calibMagErr: `~numpy.ndarray` or `~pandas.Series`
1825 Error on calibrated AB magnitudes.
1828 if localCalibErr
is not None:
1829 warnings.warn(
"The localCalibErr argument is deprecated and will be removed after v29.",
1830 category=FutureWarning)
1836 """Compute calibrated fluxes using the local calibration value.
1838 This returns units of nanojanskys.
1847 return f
'flux_{self.instFluxCol}'
1855 """Compute calibrated flux errors using the local calibration value.
1857 This returns units of nanojanskys.
1866 return f
'fluxErr_{self.instFluxCol}'
1874 """Compute absolute mean of dipole fluxes.
1880 LocalDipoleMeanFluxErr
1882 LocalDipoleDiffFluxErr
1891 photoCalibErrCol=None,
1912 return f
'dipMeanFlux_{self.instFluxPosCol}_{self.instFluxNegCol}'
1920 """Compute the error on the absolute mean of dipole fluxes.
1928 LocalDipoleDiffFluxErr
1941 return f
'dipMeanFluxErr_{self.instFluxPosCol}_{self.instFluxNegCol}'
1948 """Compute the absolute difference of dipole fluxes.
1950 Calculated value is (abs(pos) - abs(neg)).
1957 LocalDipoleMeanFluxErr
1958 LocalDipoleDiffFluxErr
1969 return f
'dipDiffFlux_{self.instFluxPosCol}_{self.instFluxNegCol}'
1977 """Compute the error on the absolute difference of dipole fluxes.
1984 LocalDipoleMeanFluxErr
1998 return f
'dipDiffFluxErr_{self.instFluxPosCol}_{self.instFluxNegCol}'
2005 """Compute E(B-V) from dustmaps.sfd."""
2006 _defaultDataset =
'ref'
2013 with open(os.devnull,
"w")
as devnull:
2014 with redirect_stdout(devnull):
2015 from dustmaps.sfd
import SFDQuery
2021 coords = SkyCoord(df[
'coord_ra'].values * u.rad, df[
'coord_dec'].values * u.rad)
2022 ebv = self.
sfd(coords)
2023 return pd.Series(ebv, index=df.index).astype(
'float32')
2027 """Base class for functors that use shape moments and localWCS
2031 is_covariance : bool
2032 Whether the shape columns are terms of a covariance matrix. If False,
2033 they will be assumed to be terms of a correlation matrix instead.
2036 is_covariance: bool =
True
2066 """Return columns that are needed from the ref table."""
2074 r"""Return terms commonly used for ellipse parameterization conversions.
2081 Whether to compute the terms in sky coordinates.
2082 If False, XX, YY and XY moments are used instead of
2088 The sum of the diagonal terms of the covariance.
2090 The difference of the diagonal terms of the covariance.
2092 A term similar to the discriminant of the quadratic formula.
2097 t2 = xx_m_yy**2 + 4.0*(self.
sky_uv(df)
if sky
else self.
get_xy(df))**2
2101 return xx + yy, xx_m_yy, t2
2118 """Return the component of the moments tensor aligned with the RA axis, in radians."""
2124 return (CD_1_1*(i_xx*CD_1_1 + i_xy*CD_1_2)
2125 + CD_1_2*(i_xy*CD_1_1 + i_yy*CD_1_2))
2128 """Return the component of the moments tensor aligned with the dec axis, in radians."""
2134 return (CD_2_1*(i_xx*CD_2_1 + i_xy*CD_2_2)
2135 + CD_2_2*(i_xy*CD_2_1 + i_yy*CD_2_2))
2138 """Return the covariance of the moments tensor in ra, dec coordinates, in radians."""
2146 return ((CD_1_1 * i_xx + CD_1_2 * i_xy) * CD_2_1
2147 + (CD_1_1 * i_xy + CD_1_2 * i_yy) * CD_2_2)
2151 Calculate shear-type ellipticity parameter G1.
2157 denom = sky_uu + sky_vv + 2 * np.sqrt(sky_uu*sky_vv - sky_uv**2)
2158 return ((sky_uu - sky_vv) / denom).astype(np.float32)
2162 Calculate shear-type ellipticity parameter G2.
2164 This has the opposite sign as sky_uv in order to maintain consistency with the HSM moments
2171 denom = sky_uu + sky_vv + 2 * np.sqrt(sky_uu*sky_vv - sky_uv**2)
2172 return (-2*sky_uv / denom).astype(np.float32)
2177 return np.sqrt(0.5*(sky_uu + sky_vv)).astype(np.float32)
2181 """Rotate pixel moments Ixx,Iyy,Ixy into RA/dec frame and G1/G2 reduced
2182 shear parameterization"""
2183 _defaultDataset =
'meas'
2185 shortname =
"moments_g1"
2190 return pd.Series(sky_g1.astype(np.float32), index=df.index)
2194 """Rotate pixel moments Ixx,Iyy,Ixy into RA/dec frame and G1/G2 reduced
2195 shear parameterization"""
2196 _defaultDataset =
'meas'
2198 shortname =
"moments_g2"
2203 return pd.Series(sky_g2.astype(np.float32), index=df.index)
2207 """Trace radius size in arcseconds from pixel moments Ixx,Iyy,Ixy
2209 The trace radius size is a measure of size equal to the square root of
2210 half of the trace of the second moments tensor.
2212 _defaultDataset =
'meas'
2213 name =
"moments_trace"
2214 shortname =
"moments_trace"
2219 return pd.Series((sky_trace_radians*(180/np.pi)*3600).astype(np.float32), index=df.index)
2223 """Rotate pixel moments Ixx,Iyy,Ixy into ra,dec frame and arcseconds"""
2224 _defaultDataset =
'meas'
2226 shortname =
"moments_uu"
2229 sky_uu_radians = self.
sky_uu(df)
2231 return pd.Series((sky_uu_radians*((180/np.pi)*3600)**2).astype(np.float32), index=df.index)
2235 """MomentsIuuSky but from sigma_x, sigma_y, rho correlation terms."""
2236 is_covariance =
False
2240 """Rotate pixel moments Ixx,Iyy,Ixy into ra,dec frame and arcseconds"""
2241 _defaultDataset =
'meas'
2243 shortname =
"moments_vv"
2246 sky_vv_radians = self.
sky_vv(df)
2248 return pd.Series((sky_vv_radians*((180/np.pi)*3600)**2).astype(np.float32), index=df.index)
2252 """MomentsIvvSky but from sigma_x, sigma_y, rho correlation terms."""
2253 is_covariance =
False
2257 """Rotate pixel moments Ixx,Iyy,Ixy into ra,dec frame and arcseconds"""
2258 _defaultDataset =
'meas'
2260 shortname =
"moments_uv"
2263 sky_uv_radians = self.
sky_uv(df)
2265 return pd.Series((sky_uv_radians*((180/np.pi)*3600)**2).astype(np.float32), index=df.index)
2269 """MomentsIuvSky but from sigma_x, sigma_y, rho correlation terms."""
2270 is_covariance =
False
2274 """Compute position angle relative to ra,dec frame, in degrees, from Ixx,Iyy,Ixy pixel moments."""
2275 _defaultDataset =
'meas'
2276 name =
"moments_theta"
2277 shortname =
"moments_theta"
2283 theta = 0.5*np.arctan2(2*sky_uv, sky_uu - sky_vv)
2285 return pd.Series((np.degrees(np.array(theta))).astype(np.float32), index=df.index)
2289 """PositionAngleFromMoments but from sigma_x, sigma_y, rho correlation terms."""
2290 is_covariance =
False
2294 """Compute the semimajor axis length in arcseconds, from Ixx,Iyy,Ixy pixel moments."""
2295 _defaultDataset =
'meas'
2297 shortname =
"moments_a"
2302 a_radians = np.sqrt(0.5 * (xx_p_yy + np.sqrt(t2)))
2304 return pd.Series((np.degrees(a_radians)*3600).astype(np.float32), index=df.index)
2308 """SemimajorAxisFromMoments but from sigma_x, sigma_y, rho correlation terms."""
2309 is_covariance =
False
2313 """Compute the semiminor axis length in arcseconds, from Ixx,Iyy,Ixy pixel moments."""
2314 _defaultDataset =
'meas'
2316 shortname =
"moments_b"
2321 b_radians = np.sqrt(0.5 * (xx_p_yy - np.sqrt(t2)))
2323 return pd.Series((np.degrees(b_radians)*3600).astype(np.float32), index=df.index)
2327 """SemiminorAxisFromMoments but from sigma_x, sigma_y, rho correlation terms."""
2328 is_covariance =
False
__init__(self, col, filt2, filt1, **kwargs)
multilevelColumns(self, parq, **kwargs)
__init__(self, col, **kwargs)
multilevelColumns(self, data, **kwargs)
__call__(self, data, **kwargs)
from_file(cls, filename, **kwargs)
renameCol(cls, col, renameRules)
from_yaml(cls, translationDefinition, **kwargs)
__init__(self, funcs, **kwargs)
pixelScaleArcseconds(self, cd11, cd12, cd21, cd22)
__init__(self, theta_err_col, **kwargs)
__init__(self, theta_col, colCD_1_1, colCD_1_2, colCD_2_1, colCD_2_2, **kwargs)
__init__(self, col, colCD_1_1, colCD_1_2, colCD_2_1, colCD_2_2, **kwargs)
__init__(self, col, colCD_1_1, colCD_1_2, colCD_2_1, colCD_2_2, **kwargs)
__init__(self, col, **kwargs)
__init__(self, expr, **kwargs)
__call__(self, catalog, **kwargs)
__init__(self, colXX, colXY, colYY, **kwargs)
__init__(self, colXX, colXY, colYY, **kwargs)
_func(self, df, dropna=True)
_get_columnIndex(self, data)
multilevelColumns(self, data, columnIndex=None, returnTuple=False)
__call__(self, data, dropna=False)
_get_data_columnLevels(self, data, columnIndex=None)
_colsFromDict(self, colDict, columnIndex=None)
difference(self, data1, data2, **kwargs)
_get_data_columnLevelNames(self, data, columnIndex=None)
__init__(self, filt=None, dataset=None, noDup=None)
__init__(self, ra, dec, **kwargs)
__init__(self, instFluxPosCol, instFluxNegCol, instFluxPosErrCol, instFluxNegErrCol, photoCalibCol, photoCalibErrCol=None, **kwargs)
instFluxToNanojansky(self, instFlux, localCalib)
instFluxErrToMagnitudeErr(self, instFlux, instFluxErr, localCalib, localCalibErr=None)
instFluxToMagnitude(self, instFlux, localCalib)
__init__(self, instFluxCol, instFluxErrCol, photoCalibCol, photoCalibErrCol=None, **kwargs)
instFluxErrToNanojanskyErr(self, instFlux, instFluxErr, localCalib, localCalibErr=None)
computeSkySeparation(self, ra1, dec1, ra2, dec2)
__init__(self, colCD_1_1, colCD_1_2, colCD_2_1, colCD_2_2, **kwargs)
computeDeltaRaDec(self, x, y, cd11, cd12, cd21, cd22)
getSkySeparationFromPixel(self, x1, y1, x2, y2, cd11, cd12, cd21, cd22)
computePositionAngle(self, ra1, dec1, ra2, dec2)
getPositionAngleFromDetectorAngle(self, theta, cd11, cd12, cd21, cd22)
__init__(self, col1, col2, **kwargs)
__init__(self, *args, **kwargs)
__init__(self, col, **kwargs)
__init__(self, shape_1_1, shape_2_2, shape_1_2, colCD_1_1, colCD_1_2, colCD_2_1, colCD_2_2, **kwargs)
compute_ellipse_terms(self, df, bool sky=True)
__init__(self, col, band_to_check, **kwargs)
dn2flux(self, dn, fluxMag0)
__init__(self, colFlux, colFluxErr=None, **kwargs)
dn2mag(self, dn, fluxMag0)
dn2MagErr(self, dn, dnErr, fluxMag0, fluxMag0Err)
dn2fluxErr(self, dn, dnErr, fluxMag0, fluxMag0Err)
__call__(self, catalog, **kwargs)
__init__(self, colXX, colXY, colYY, **kwargs)
pd.Series _func(self, pd.DataFrame df)
__init__(self, tuple[str]|list[str]|None bands=None, **kwargs)
init_fromDict(initDict, basePath='lsst.pipe.tasks.functors', typeKey='functor', name=None)
mag_aware_eval(df, expr, log)