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 "ReferenceBand",
"Photometry",
32 "NanoJansky",
"NanoJanskyErr",
"LocalPhotometry",
"LocalNanojansky",
33 "LocalNanojanskyErr",
"LocalDipoleMeanFlux",
34 "LocalDipoleMeanFluxErr",
"LocalDipoleDiffFlux",
35 "LocalDipoleDiffFluxErr",
"Ebv",
36 "MomentsIuuSky",
"MomentsIvvSky",
"MomentsIuvSky",
37 "CorrelationIuuSky",
"CorrelationIvvSky",
"CorrelationIuvSky",
38 "PositionAngleFromMoments",
"PositionAngleFromCorrelation",
39 "SemimajorAxisFromMoments",
"SemimajorAxisFromCorrelation",
40 "SemiminorAxisFromMoments",
"SemiminorAxisFromCorrelation",
48from contextlib
import redirect_stdout
49from itertools
import product
51import astropy.units
as u
57from astropy.coordinates
import SkyCoord
58from lsst.daf.butler
import DeferredDatasetHandle
59from lsst.pipe.base
import InMemoryDatasetHandle
60from lsst.utils
import doImport
61from lsst.utils.introspection
import get_full_type_name
65 typeKey='functor', name=None):
66 """Initialize an object defined in a dictionary.
68 The object needs to be importable as f'{basePath}.{initDict[typeKey]}'.
69 The positional and keyword arguments (if any) are contained in "args" and
70 "kwargs" entries in the dictionary, respectively.
71 This is used in `~lsst.pipe.tasks.functors.CompositeFunctor.from_yaml` to
72 initialize a composite functor from a specification in a YAML file.
77 Dictionary describing object's initialization.
78 Must contain an entry keyed by ``typeKey`` that is the name of the
79 object, relative to ``basePath``.
81 Path relative to module in which ``initDict[typeKey]`` is defined.
83 Key of ``initDict`` that is the name of the object (relative to
86 initDict = initDict.copy()
88 pythonType = doImport(f
'{basePath}.{initDict.pop(typeKey)}')
90 if 'args' in initDict:
91 args = initDict.pop(
'args')
92 if isinstance(args, str):
95 element = pythonType(*args, **initDict)
96 except Exception
as e:
97 message = f
'Error in constructing functor "{name}" of type {pythonType.__name__} with args: {args}'
98 raise type(e)(message, e.args)
103 """Define and execute a calculation on a DataFrame or Handle holding a
106 The `__call__` method accepts either a `~pandas.DataFrame` object or a
107 `~lsst.daf.butler.DeferredDatasetHandle` or
108 `~lsst.pipe.base.InMemoryDatasetHandle`, and returns the
109 result of the calculation as a single column.
110 Each functor defines what columns are needed for the calculation, and only
111 these columns are read from the dataset handle.
113 The action of `__call__` consists of two steps: first, loading the
114 necessary columns from disk into memory as a `~pandas.DataFrame` object;
115 and second, performing the computation on this DataFrame and returning the
118 To define a new `Functor`, a subclass must define a `_func` method,
119 that takes a `~pandas.DataFrame` and returns result in a `~pandas.Series`.
120 In addition, it must define the following attributes:
122 * `_columns`: The columns necessary to perform the calculation
123 * `name`: A name appropriate for a figure axis label
124 * `shortname`: A name appropriate for use as a dictionary key
126 On initialization, a `Functor` should declare what band (``filt`` kwarg)
127 and dataset (e.g. ``'ref'``, ``'meas'``, ``'forced_src'``) it is intended
129 This enables the `_get_data` method to extract the proper columns from the
131 If not specified, the dataset will fall back on the `_defaultDataset`
133 If band is not specified and ``dataset`` is anything other than ``'ref'``,
134 then an error will be raised when trying to perform the calculation.
136 Originally, `Functor` was set up to expect datasets formatted like the
137 ``deepCoadd_obj`` dataset; that is, a DataFrame with a multi-level column
138 index, with the levels of the column index being ``band``, ``dataset``, and
140 It has since been generalized to apply to DataFrames without multi-level
141 indices and multi-level indices with just ``dataset`` and ``column``
143 In addition, the `_get_data` method that reads the columns from the
144 underlying data will return a DataFrame with column index levels defined by
145 the `_dfLevels` attribute; by default, this is ``column``.
147 The `_dfLevels` attributes should generally not need to be changed, unless
148 `_func` needs columns from multiple filters or datasets to do the
150 An example of this is the `~lsst.pipe.tasks.functors.Color` functor, for
151 which `_dfLevels = ('band', 'column')`, and `_func` expects the DataFrame
152 it gets to have those levels in the column index.
157 Band upon which to do the calculation.
160 Dataset upon which to do the calculation (e.g., 'ref', 'meas',
164 _defaultDataset =
'ref'
165 _dfLevels = (
'column',)
166 _defaultNoDup =
False
168 def __init__(self, filt=None, dataset=None, noDup=None):
172 self.
log = logging.getLogger(type(self).__name__)
176 """Do not explode by band if used on object table."""
177 if self.
_noDup is not None:
184 """Columns required to perform calculation."""
185 if not hasattr(self,
'_columns'):
186 raise NotImplementedError(
'Must define columns property or _columns attribute')
190 """Gets the names of the column index levels.
192 This should only be called in the context of a multilevel table.
197 The data to be read, can be a
198 `~lsst.daf.butler.DeferredDatasetHandle` or
199 `~lsst.pipe.base.InMemoryDatasetHandle`.
200 columnIndex (optional): pandas `~pandas.Index` object
201 If not passed, then it is read from the
202 `~lsst.daf.butler.DeferredDatasetHandle`
203 for `~lsst.pipe.base.InMemoryDatasetHandle`.
205 if columnIndex
is None:
206 columnIndex = data.get(component=
"columns")
207 return columnIndex.names
210 """Gets the content of each of the column levels for a multilevel
213 if columnIndex
is None:
214 columnIndex = data.get(component=
"columns")
216 columnLevels = columnIndex.names
218 level: list(np.unique(np.array([c
for c
in columnIndex])[:, i]))
219 for i, level
in enumerate(columnLevels)
221 return columnLevelNames
224 """Converts dictionary column specficiation to a list of columns."""
228 for i, lev
in enumerate(columnLevels):
230 if isinstance(colDict[lev], str):
231 new_colDict[lev] = [colDict[lev]]
233 new_colDict[lev] = colDict[lev]
235 new_colDict[lev] = columnIndex.levels[i]
237 levelCols = [new_colDict[lev]
for lev
in columnLevels]
238 cols = list(product(*levelCols))
239 colsAvailable = [col
for col
in cols
if col
in columnIndex]
243 """Returns columns needed by functor from multilevel dataset.
245 To access tables with multilevel column structure, the
246 `~lsst.daf.butler.DeferredDatasetHandle` or
247 `~lsst.pipe.base.InMemoryDatasetHandle` needs to be passed
248 either a list of tuples or a dictionary.
253 The data as either `~lsst.daf.butler.DeferredDatasetHandle`, or
254 `~lsst.pipe.base.InMemoryDatasetHandle`.
255 columnIndex (optional): pandas `~pandas.Index` object
256 Either passed or read in from
257 `~lsst.daf.butler.DeferredDatasetHandle`.
258 `returnTuple` : `bool`
259 If true, then return a list of tuples rather than the column
260 dictionary specification.
261 This is set to `True` by `CompositeFunctor` in order to be able to
262 combine columns from the various component functors.
265 if not isinstance(data, (DeferredDatasetHandle, InMemoryDatasetHandle)):
266 raise RuntimeError(f
"Unexpected data type. Got {get_full_type_name(data)}.")
268 if columnIndex
is None:
269 columnIndex = data.get(component=
"columns")
275 columnDict = {
'column': self.
columns,
277 if self.
filt is None:
279 if "band" in columnLevels:
281 columnDict[
"band"] = columnLevelNames[
"band"][0]
283 raise ValueError(f
"'filt' not set for functor {self.name}"
284 f
"(dataset {self.dataset}) "
286 "contains multiple filters in column index. "
287 "Set 'filt' or set 'dataset' to 'ref'.")
289 columnDict[
'band'] = self.
filt
292 return self.
_colsFromDict(columnDict, columnIndex=columnIndex)
297 raise NotImplementedError(
'Must define calculation on DataFrame')
300 """Return columnIndex."""
302 if isinstance(data, (DeferredDatasetHandle, InMemoryDatasetHandle)):
303 return data.get(component=
"columns")
308 """Retrieve DataFrame necessary for calculation.
310 The data argument can be a `~pandas.DataFrame`, a
311 `~lsst.daf.butler.DeferredDatasetHandle`, or
312 an `~lsst.pipe.base.InMemoryDatasetHandle`.
314 Returns a DataFrame upon which `self._func` can act.
318 if isinstance(data, pd.DataFrame):
319 _data = InMemoryDatasetHandle(data, storageClass=
"DataFrame")
320 elif isinstance(data, (DeferredDatasetHandle, InMemoryDatasetHandle)):
323 raise RuntimeError(f
"Unexpected type provided for data. Got {get_full_type_name(data)}.")
328 is_multiLevel = isinstance(columnIndex, pd.MultiIndex)
337 df = _data.get(parameters={
"columns": columns})
346 levelsToDrop = [n
for n
in df.columns.names
if n
not in self.
_dfLevels]
347 df.columns = df.columns.droplevel(levelsToDrop)
356 vals = self.
_func(df)
357 except Exception
as e:
358 self.
log.error(
"Exception in %s call: %s: %s", self.
name, type(e).__name__, e)
366 """Computes difference between functor called on two different
367 DataFrame/Handle objects.
369 return self(data1, **kwargs) -
self(data2, **kwargs)
372 return pd.Series(np.full(len(df), np.nan), index=df.index)
376 """Full name of functor (suitable for figure labels)."""
377 return NotImplementedError
381 """Short name of functor (suitable for column name/dict key)."""
386 """Perform multiple calculations at once on a catalog.
388 The role of a `CompositeFunctor` is to group together computations from
390 Instead of returning `~pandas.Series` a `CompositeFunctor` returns a
391 `~pandas.DataFrame`, with the column names being the keys of ``funcDict``.
393 The `columns` attribute of a `CompositeFunctor` is the union of all columns
394 in all the component functors.
396 A `CompositeFunctor` does not use a `_func` method itself; rather, when a
397 `CompositeFunctor` is called, all its columns are loaded at once, and the
398 resulting DataFrame is passed to the `_func` method of each component
400 This has the advantage of only doing I/O (reading from parquet file) once,
401 and works because each individual `_func` method of each component functor
402 does not care if there are *extra* columns in the DataFrame being passed;
403 only that it must contain *at least* the `columns` it expects.
405 An important and useful class method is `from_yaml`, which takes as an
406 argument the path to a YAML file specifying a collection of functors.
410 funcs : `dict` or `list`
411 Dictionary or list of functors.
412 If a list, then it will be converted into a dictonary according to the
413 `.shortname` attribute of each functor.
416 name =
"CompositeFunctor"
420 if type(funcs)
is dict:
423 self.
funcDict = {f.shortname: f
for f
in funcs}
441 """Update the functor with new functors."""
442 if isinstance(new, dict):
444 elif isinstance(new, CompositeFunctor):
447 raise TypeError(
'Can only update with dictionary or CompositeFunctor.')
450 if self.
filt is not None:
455 return list(set([x
for y
in [f.columns
for f
in self.
funcDict.values()]
for x
in y]))
465 f.multilevelColumns(data, returnTuple=
True, **kwargs)
for f
in self.
funcDict.values()
473 """Apply the functor to the data table.
478 The data represented as `~lsst.daf.butler.DeferredDatasetHandle`,
479 `~lsst.pipe.base.InMemoryDatasetHandle`, or `~pandas.DataFrame`.
480 The table or a pointer to a table on disk from which columns can
483 if isinstance(data, pd.DataFrame):
484 _data = InMemoryDatasetHandle(data, storageClass=
"DataFrame")
485 elif isinstance(data, (DeferredDatasetHandle, InMemoryDatasetHandle)):
488 raise RuntimeError(f
"Unexpected type provided for data. Got {get_full_type_name(data)}.")
492 if isinstance(columnIndex, pd.MultiIndex):
494 df = _data.get(parameters={
"columns": columns})
499 subdf = f._setLevels(
500 df[f.multilevelColumns(_data, returnTuple=
True, columnIndex=columnIndex)]
502 valDict[k] = f._func(subdf)
503 except Exception
as e:
505 "Exception in %s (funcs: %s) call: %s",
511 valDict[k] = f.fail(subdf)
516 df = _data.get(parameters={
"columns": self.
columns})
518 valDict = {k: f._func(df)
for k, f
in self.
funcDict.items()}
521 for name, colVal
in valDict.items():
522 if len(colVal.shape) != 1:
523 raise RuntimeError(
"Transformed column '%s' is not the shape of a column. "
524 "It is shaped %s and type %s." % (name, colVal.shape, type(colVal)))
527 valDf = pd.concat(valDict, axis=1)
529 print([(k, type(v))
for k, v
in valDict.items()])
532 if kwargs.get(
'dropna',
False):
533 valDf = valDf.dropna(how=
'any')
539 if renameRules
is None:
541 for old, new
in renameRules:
542 if col.startswith(old):
543 col = col.replace(old, new)
549 filename = os.path.expandvars(filename)
550 with open(filename)
as f:
551 translationDefinition = yaml.safe_load(f)
553 return cls.
from_yaml(translationDefinition, **kwargs)
558 for func, val
in translationDefinition[
'funcs'].items():
561 if 'flag_rename_rules' in translationDefinition:
562 renameRules = translationDefinition[
'flag_rename_rules']
566 if 'calexpFlags' in translationDefinition:
567 for flag
in translationDefinition[
'calexpFlags']:
568 funcs[cls.
renameCol(flag, renameRules)] =
Column(flag, dataset=
'calexp')
570 if 'refFlags' in translationDefinition:
571 for flag
in translationDefinition[
'refFlags']:
574 if 'forcedFlags' in translationDefinition:
575 for flag
in translationDefinition[
'forcedFlags']:
576 funcs[cls.
renameCol(flag, renameRules)] =
Column(flag, dataset=
'forced_src')
578 if 'flags' in translationDefinition:
579 for flag
in translationDefinition[
'flags']:
582 return cls(funcs, **kwargs)
586 """Evaluate an expression on a DataFrame, knowing what the 'mag' function
589 Builds on `pandas.DataFrame.eval`, which parses and executes math on
594 df : ~pandas.DataFrame
595 DataFrame on which to evaluate expression.
601 expr_new = re.sub(
r'mag\((\w+)\)',
r'-2.5*log(\g<1>)/log(10)', expr)
602 val = df.eval(expr_new)
603 except Exception
as e:
604 log.error(
"Exception in mag_aware_eval: %s: %s", type(e).__name__, e)
605 expr_new = re.sub(
r'mag\((\w+)\)',
r'-2.5*log(\g<1>_instFlux)/log(10)', expr)
606 val = df.eval(expr_new)
611 """Arbitrary computation on a catalog.
613 Column names (and thus the columns to be loaded from catalog) are found by
614 finding all words and trying to ignore all "math-y" words.
619 Expression to evaluate, to be parsed and executed by
620 `~lsst.pipe.tasks.functors.mag_aware_eval`.
622 _ignore_words = (
'mag',
'sin',
'cos',
'exp',
'log',
'sqrt')
634 flux_cols = re.findall(
r'mag\(\s*(\w+)\s*\)', self.
expr)
636 cols = [c
for c
in re.findall(
r'[a-zA-Z_]+', self.
expr)
if c
not in self.
_ignore_words]
639 if not re.search(
'_instFlux$', c):
640 cols.append(f
'{c}_instFlux')
645 return list(set([c
for c
in cols
if c
not in not_a_col]))
652 """Get column with a specified name."""
671 """Return the value of the index for each object."""
673 columns = [
'coord_ra']
674 _defaultDataset =
'ref'
678 return pd.Series(df.index, index=df.index)
682 """Base class for coordinate column, in degrees."""
691 output = df[self.
col] * 180 / np.pi
if self.
_radians else df[self.
col]
696 """Right Ascension, in degrees."""
701 super().
__init__(
'coord_ra', **kwargs)
704 return super().
__call__(catalog, **kwargs)
708 """Declination, in degrees."""
713 super().
__init__(
'coord_dec', **kwargs)
716 return super().
__call__(catalog, **kwargs)
720 """Uncertainty in Right Ascension, in degrees."""
725 super().
__init__(
'coord_raErr', **kwargs)
729 """Uncertainty in declination, in degrees."""
734 super().
__init__(
'coord_decErr', **kwargs)
738 """Coordinate covariance column, in degrees."""
744 super().
__init__(
'coord_ra_dec_Cov', **kwargs)
749 output = df[self.
col]*(180/np.pi)**2
if self.
_radians else df[self.
col]
754 """A column with a band in a multiband table."""
765 """A float32 MultibandColumn"""
767 return super().
_func(df).astype(np.float32)
771 """Return a column cast to a single-precision float."""
774 return df[self.
col].astype(np.float32)
778 """Compute the level 20 HtmIndex for the catalog.
782 This functor was implemented to satisfy requirements of old APDB interface
783 which required the ``pixelId`` column in DiaObject with HTM20 index.
784 The APDB interface had migrated to not need that information, but we keep
785 this class in case it may be useful for something else.
800 def computePixel(row):
809 return self.
pixelator.index(sphPoint.getVector())
811 return df.apply(computePixel, axis=1, result_type=
'reduce').astype(
'int64')
815 """Append _instFlux to the column name if it doesn't have it already."""
816 if not col.endswith(
'_instFlux'):
822 """Append _instFluxErr to the column name if it doesn't have it already."""
823 if not col.endswith(
'_instFluxErr'):
824 col +=
'_instFluxErr'
829 """Compute calibrated magnitude.
831 Returns the flux at mag=0.
832 The default ``fluxMag0`` is 63095734448.0194, which is default for HSC.
833 TO DO: This default should be made configurable in DM-21955.
835 This calculation hides warnings about invalid values and dividing by zero.
837 As with all functors, a ``dataset`` and ``filt`` kwarg should be provided
839 Unlike the default `Functor`, however, the default dataset for a `Mag` is
840 ``'meas'``, rather than ``'ref'``.
845 Name of flux column from which to compute magnitude.
846 Can be parseable by the `~lsst.pipe.tasks.functors.fluxName` function;
847 that is, you can pass ``'modelfit_CModel'`` instead of
848 ``'modelfit_CModel_instFlux'``, and it will understand.
850 _defaultDataset =
'meas'
864 with warnings.catch_warnings():
865 warnings.filterwarnings(
'ignore',
r'invalid value encountered')
866 warnings.filterwarnings(
'ignore',
r'divide by zero')
871 return f
'mag_{self.col}'
875 """Compute calibrated magnitude uncertainty.
880 Name of the flux column.
893 with warnings.catch_warnings():
894 warnings.filterwarnings(
'ignore',
r'invalid value encountered')
895 warnings.filterwarnings(
'ignore',
r'divide by zero')
896 fluxCol, fluxErrCol = self.
columns
897 x = df[fluxErrCol] / df[fluxCol]
899 magErr = (2.5 / np.log(10.)) * np.sqrt(x*x + y*y)
904 return super().name +
'_err'
908 """Functor to calculate magnitude difference."""
909 _defaultDataset =
'meas'
921 with warnings.catch_warnings():
922 warnings.filterwarnings(
'ignore',
r'invalid value encountered')
923 warnings.filterwarnings(
'ignore',
r'divide by zero')
924 return -2.5*np.log10(df[self.
col1]/df[self.
col2])
928 return f
'(mag_{self.col1} - mag_{self.col2})'
932 return f
'magDiff_{self.col1}_{self.col2}'
936 """Compute the color between two filters.
938 Computes color by initializing two different `Mag` functors based on the
939 ``col`` and filters provided, and then returning the difference.
941 This is enabled by the `_func` method expecting a DataFrame with a
942 multilevel column index, with both ``'band'`` and ``'column'``, instead of
943 just ``'column'``, which is the `Functor` default.
944 This is controlled by the `_dfLevels` attribute.
946 Also of note, the default dataset for `Color` is ``forced_src'``, whereas
947 for `Mag` it is ``'meas'``.
952 Name of the flux column from which to compute; same as would be passed
953 to `~lsst.pipe.tasks.functors.Mag`.
956 Filters from which to compute magnitude difference.
957 Color computed is ``Mag(filt2) - Mag(filt1)``.
959 _defaultDataset =
'forced_src'
960 _dfLevels = (
'band',
'column')
966 raise RuntimeError(
"Cannot compute Color for %s: %s - %s " % (col, filt2, filt1))
984 mag2 = self.mag2.
_func(df[self.filt2])
985 mag1 = self.mag1.
_func(df[self.filt1])
990 return [self.
mag1.col, self.
mag2.col]
997 return f
'{self.filt2} - {self.filt1} ({self.col})'
1001 return f
"{self.col}_{self.filt2.replace('-', '')}m{self.filt1.replace('-', '')}"
1005 """This functor subtracts the trace of the PSF second moments from the
1006 trace of the second moments of the source.
1008 If the HsmShapeAlgorithm measurement is valid, then these will be used for
1010 Otherwise, the SdssShapeAlgorithm measurements will be used.
1012 name =
'Deconvolved Moments'
1013 shortname =
'deconvolvedMoments'
1014 _columns = (
"ext_shapeHSM_HsmSourceMoments_xx",
1015 "ext_shapeHSM_HsmSourceMoments_yy",
1016 "base_SdssShape_xx",
"base_SdssShape_yy",
1017 "ext_shapeHSM_HsmPsfMoments_xx",
1018 "ext_shapeHSM_HsmPsfMoments_yy")
1021 """Calculate deconvolved moments."""
1022 if "ext_shapeHSM_HsmSourceMoments_xx" in df.columns:
1023 hsm = df[
"ext_shapeHSM_HsmSourceMoments_xx"] + df[
"ext_shapeHSM_HsmSourceMoments_yy"]
1025 hsm = np.ones(len(df))*np.nan
1026 sdss = df[
"base_SdssShape_xx"] + df[
"base_SdssShape_yy"]
1027 if "ext_shapeHSM_HsmPsfMoments_xx" in df.columns:
1028 psf = df[
"ext_shapeHSM_HsmPsfMoments_xx"] + df[
"ext_shapeHSM_HsmPsfMoments_yy"]
1033 raise RuntimeError(
'No psf shape parameter found in catalog')
1035 return hsm.where(np.isfinite(hsm), sdss) - psf
1039 """Functor to calculate the SDSS trace radius size for sources.
1041 The SDSS trace radius size is a measure of size equal to the square root of
1042 half of the trace of the second moments tensor measured with the
1043 SdssShapeAlgorithm plugin.
1044 This has units of pixels.
1046 name =
"SDSS Trace Size"
1047 shortname =
'sdssTrace'
1048 _columns = (
"base_SdssShape_xx",
"base_SdssShape_yy")
1051 srcSize = np.sqrt(0.5*(df[
"base_SdssShape_xx"] + df[
"base_SdssShape_yy"]))
1056 """Functor to calculate the SDSS trace radius size difference (%) between
1057 the object and the PSF model.
1063 name =
"PSF - SDSS Trace Size"
1064 shortname =
'psf_sdssTrace'
1065 _columns = (
"base_SdssShape_xx",
"base_SdssShape_yy",
1066 "base_SdssShape_psf_xx",
"base_SdssShape_psf_yy")
1069 srcSize = np.sqrt(0.5*(df[
"base_SdssShape_xx"] + df[
"base_SdssShape_yy"]))
1070 psfSize = np.sqrt(0.5*(df[
"base_SdssShape_psf_xx"] + df[
"base_SdssShape_psf_yy"]))
1071 sizeDiff = 100*(srcSize - psfSize)/(0.5*(srcSize + psfSize))
1076 """Functor to calculate the HSM trace radius size for sources.
1078 The HSM trace radius size is a measure of size equal to the square root of
1079 half of the trace of the second moments tensor measured with the
1080 HsmShapeAlgorithm plugin.
1081 This has units of pixels.
1083 name =
'HSM Trace Size'
1084 shortname =
'hsmTrace'
1085 _columns = (
"ext_shapeHSM_HsmSourceMoments_xx",
1086 "ext_shapeHSM_HsmSourceMoments_yy")
1089 srcSize = np.sqrt(0.5*(df[
"ext_shapeHSM_HsmSourceMoments_xx"]
1090 + df[
"ext_shapeHSM_HsmSourceMoments_yy"]))
1095 """Functor to calculate the HSM trace radius size difference (%) between
1096 the object and the PSF model.
1102 name =
'PSF - HSM Trace Size'
1103 shortname =
'psf_HsmTrace'
1104 _columns = (
"ext_shapeHSM_HsmSourceMoments_xx",
1105 "ext_shapeHSM_HsmSourceMoments_yy",
1106 "ext_shapeHSM_HsmPsfMoments_xx",
1107 "ext_shapeHSM_HsmPsfMoments_yy")
1110 srcSize = np.sqrt(0.5*(df[
"ext_shapeHSM_HsmSourceMoments_xx"]
1111 + df[
"ext_shapeHSM_HsmSourceMoments_yy"]))
1112 psfSize = np.sqrt(0.5*(df[
"ext_shapeHSM_HsmPsfMoments_xx"]
1113 + df[
"ext_shapeHSM_HsmPsfMoments_yy"]))
1114 sizeDiff = 100*(srcSize - psfSize)/(0.5*(srcSize + psfSize))
1119 """Functor to calculate the PSF FWHM with second moments measured from the
1120 HsmShapeAlgorithm plugin.
1122 This is in units of arcseconds, and assumes the hsc_rings_v1 skymap pixel
1123 scale of 0.168 arcseconds/pixel.
1127 This conversion assumes the PSF is Gaussian, which is not always the case.
1129 name =
'HSM Psf FWHM'
1130 _columns = (
'ext_shapeHSM_HsmPsfMoments_xx',
'ext_shapeHSM_HsmPsfMoments_yy')
1133 SIGMA2FWHM = 2*np.sqrt(2*np.log(2))
1137 0.5*(df[
'ext_shapeHSM_HsmPsfMoments_xx']
1138 + df[
'ext_shapeHSM_HsmPsfMoments_yy']))).astype(np.float32)
1142 r"""Calculate :math:`e_1` ellipticity component for sources, defined as:
1145 e_1 &= (I_{xx}-I_{yy})/(I_{xx}+I_{yy})
1151 name =
"Distortion Ellipticity (e1)"
1152 shortname =
"Distortion"
1166 return ((df[self.
colXX] - df[self.
colYY]) / (
1167 df[self.
colXX] + df[self.
colYY])).astype(np.float32)
1171 r"""Calculate :math:`e_2` ellipticity component for sources, defined as:
1174 e_2 &= 2I_{xy}/(I_{xx}+I_{yy})
1180 name =
"Ellipticity e2"
1193 return (2*df[self.
colXY] / (df[self.
colXX] + df[self.
colYY])).astype(np.float32)
1197 """Calculate the radius from the quadrupole moments.
1199 This returns the fourth root of the determinant of the second moments
1200 tensor, which has units of pixels.
1219 return ((df[self.
colXX]*df[self.
colYY] - df[self.
colXY]**2)**0.25).astype(np.float32)
1223 """Computations using the stored localWcs."""
1224 name =
"LocalWcsOperations"
1239 """Compute the dRA, dDec from dx, dy.
1243 x : `~pandas.Series`
1245 y : `~pandas.Series`
1247 cd11 : `~pandas.Series`
1248 [1, 1] element of the local Wcs affine transform.
1249 cd12 : `~pandas.Series`
1250 [1, 2] element of the local Wcs affine transform.
1251 cd21 : `~pandas.Series`
1252 [2, 1] element of the local Wcs affine transform.
1253 cd22 : `~pandas.Series`
1254 [2, 2] element of the local Wcs affine transform.
1259 RA and Dec conversion of x and y given the local Wcs.
1260 Returned units are in radians.
1264 If x and y are with respect to the CRVAL1, CRVAL2
1265 then this will return the RA, Dec for that WCS.
1267 return (x * cd11 + y * cd12, x * cd21 + y * cd22)
1270 """Compute the local pixel scale conversion.
1274 ra1 : `~pandas.Series`
1275 Ra of the first coordinate in radians.
1276 dec1 : `~pandas.Series`
1277 Dec of the first coordinate in radians.
1278 ra2 : `~pandas.Series`
1279 Ra of the second coordinate in radians.
1280 dec2 : `~pandas.Series`
1281 Dec of the second coordinate in radians.
1285 dist : `~pandas.Series`
1286 Distance on the sphere in radians.
1288 deltaDec = dec2 - dec1
1290 return 2 * np.arcsin(
1292 np.sin(deltaDec / 2) ** 2
1293 + np.cos(dec2) * np.cos(dec1) * np.sin(deltaRa / 2) ** 2))
1296 """Compute the distance on the sphere from x2, y1 to x1, y1.
1300 x1 : `~pandas.Series`
1302 y1 : `~pandas.Series`
1304 x2 : `~pandas.Series`
1306 y2 : `~pandas.Series`
1308 cd11 : `~pandas.Series`
1309 [1, 1] element of the local Wcs affine transform.
1310 cd12 : `~pandas.Series`
1311 [1, 2] element of the local Wcs affine transform.
1312 cd21 : `~pandas.Series`
1313 [2, 1] element of the local Wcs affine transform.
1314 cd22 : `~pandas.Series`
1315 [2, 2] element of the local Wcs affine transform.
1319 Distance : `~pandas.Series`
1320 Arcseconds per pixel at the location of the local WC.
1328 """Compute position angle (E of N) from (ra1, dec1) to (ra2, dec2).
1332 ra1 : iterable [`float`]
1333 RA of the first coordinate [radian].
1334 dec1 : iterable [`float`]
1335 Dec of the first coordinate [radian].
1336 ra2 : iterable [`float`]
1337 RA of the second coordinate [radian].
1338 dec2 : iterable [`float`]
1339 Dec of the second coordinate [radian].
1343 Position Angle: `~pandas.Series`
1348 (ra1, dec1) -> (ra2, dec2) is interpreted as the shorter way around the sphere
1350 For a separation of 0.0001 rad, the position angle is good to 0.0009 rad
1351 all over the sphere.
1355 position_angle = np.zeros(len(ra1))
1356 for i, (r1, d1, r2, d2)
in enumerate(zip(ra1, dec1, ra2, dec2)):
1359 bearing = point1.bearingTo(point2)
1360 pa_ref_angle =
geom.Angle(np.pi/2, geom.radians)
1361 pa = pa_ref_angle - bearing
1364 position_angle[i] = pa.asRadians()
1366 return pd.Series(position_angle)
1369 """Compute position angle (E of N) from detector angle (+y of +x).
1374 detector angle [radian]
1376 [1, 1] element of the local Wcs affine transform.
1378 [1, 2] element of the local Wcs affine transform.
1380 [2, 1] element of the local Wcs affine transform.
1382 [2, 2] element of the local Wcs affine transform.
1386 Position Angle: `~pandas.Series`
1399 """Compute the local pixel scale from the stored CDMatrix.
1411 """Compute the local pixel to scale conversion in arcseconds.
1415 cd11 : `~pandas.Series`
1416 [1, 1] element of the local Wcs affine transform in radians.
1417 cd11 : `~pandas.Series`
1418 [1, 1] element of the local Wcs affine transform in radians.
1419 cd12 : `~pandas.Series`
1420 [1, 2] element of the local Wcs affine transform in radians.
1421 cd21 : `~pandas.Series`
1422 [2, 1] element of the local Wcs affine transform in radians.
1423 cd22 : `~pandas.Series`
1424 [2, 2] element of the local Wcs affine transform in radians.
1428 pixScale : `~pandas.Series`
1429 Arcseconds per pixel at the location of the local WC.
1431 return 3600 * np.degrees(np.sqrt(np.fabs(cd11 * cd22 - cd12 * cd21)))
1441 """Convert a value in units of pixels to units of arcseconds."""
1459 return f
"{self.col}_asArcseconds"
1477 """Convert a value in units of pixels squared to units of arcseconds
1497 return f
"{self.col}_asArcsecondsSq"
1512 return df[self.
col] * pixScale * pixScale
1516 """Compute a position angle from a detector angle and the stored CDMatrix.
1520 position angle : degrees
1523 name =
"PositionAngle"
1535 super().
__init__(colCD_1_1, colCD_1_2, colCD_2_1, colCD_2_2, **kwargs)
1558 """Return the band used to seed multiband forced photometry.
1560 This functor is to be used on Object tables.
1561 It converts the boolean merge_measurements_{band} columns into a single
1562 string representing the first band for which merge_measurements_{band}
1565 Assumes the default priority order of i, r, z, y, g, u.
1567 name =
'Reference Band'
1568 shortname =
'refBand'
1570 band_order = (
"i",
"r",
"z",
"y",
"g",
"u")
1578 return [f
"merge_measurement_{band}" for band
in bands]
1580 def _func(self, df: pd.DataFrame) -> pd.Series:
1581 def getFilterAliasName(row):
1583 colName = row.idxmax()
1584 return colName.replace(
'merge_measurement_',
'')
1588 columns = [col
for col
in self.
columns if col
in df.columns]
1590 return df[columns].apply(getFilterAliasName, axis=1,
1591 result_type=
'reduce').astype(
'object')
1593 def __init__(self, bands: tuple[str] | list[str] |
None =
None, **kwargs):
1599 """Base class for Object table calibrated fluxes and magnitudes."""
1601 AB_FLUX_SCALE = (0 * u.ABmag).to_value(u.nJy)
1602 LOG_AB_FLUX_SCALE = 12.56
1603 FIVE_OVER_2LOG10 = 1.085736204758129569
1607 def __init__(self, colFlux, colFluxErr=None, **kwargs):
1623 return f
'mag_{self.col}'
1627 """Compute sqrt(a^2 + b^2) without under/overflow."""
1628 if np.abs(a) < np.abs(b):
1633 return np.abs(a) * np.sqrt(1. + q*q)
1636 """Convert instrumental flux to nanojanskys."""
1637 return (self.
AB_FLUX_SCALE * dn / fluxMag0).astype(np.float32)
1640 """Convert instrumental flux to AB magnitude."""
1641 with warnings.catch_warnings():
1642 warnings.filterwarnings(
'ignore',
r'invalid value encountered')
1643 warnings.filterwarnings(
'ignore',
r'divide by zero')
1644 return (-2.5 * np.log10(dn/fluxMag0)).astype(np.float32)
1647 """Convert instrumental flux error to nanojanskys."""
1648 retVal = self.
vhypot(dn * fluxMag0Err, dnErr * fluxMag0)
1650 return retVal.astype(np.float32)
1653 """Convert instrumental flux error to AB magnitude error."""
1654 retVal = self.
dn2fluxErr(dn, dnErr, fluxMag0, fluxMag0Err) / self.
dn2flux(dn, fluxMag0)
1659 """Convert instrumental flux to nanojanskys."""
1665 """Convert instrumental flux error to nanojanskys."""
1672 return pd.Series(retArr, index=df.index)
1676 """Base class for calibrating the specified instrument flux column using
1677 the local photometric calibration.
1682 Name of the instrument flux column.
1683 instFluxErrCol : `str`
1684 Name of the assocated error columns for ``instFluxCol``.
1685 photoCalibCol : `str`
1686 Name of local calibration column.
1687 photoCalibErrCol : `str`, optional
1688 Error associated with ``photoCalibCol``. Ignored and deprecated; will
1689 be removed after v29.
1696 logNJanskyToAB = (1 * u.nJy).to_value(u.ABmag)
1702 photoCalibErrCol=None,
1708 if photoCalibErrCol
is not None:
1709 warnings.warn(
"The photoCalibErrCol argument is deprecated and will be removed after v29.",
1710 category=FutureWarning)
1714 """Convert instrument flux to nanojanskys.
1718 instFlux : `~numpy.ndarray` or `~pandas.Series`
1719 Array of instrument flux measurements.
1720 localCalib : `~numpy.ndarray` or `~pandas.Series`
1721 Array of local photometric calibration estimates.
1725 calibFlux : `~numpy.ndarray` or `~pandas.Series`
1726 Array of calibrated flux measurements.
1728 return instFlux * localCalib
1731 """Convert instrument flux to nanojanskys.
1735 instFlux : `~numpy.ndarray` or `~pandas.Series`
1736 Array of instrument flux measurements. Ignored (accepted for
1737 backwards compatibility and consistency with magnitude-error
1738 calculation methods).
1739 instFluxErr : `~numpy.ndarray` or `~pandas.Series`
1740 Errors on associated ``instFlux`` values.
1741 localCalib : `~numpy.ndarray` or `~pandas.Series`
1742 Array of local photometric calibration estimates.
1743 localCalibErr : `~numpy.ndarray` or `~pandas.Series`, optional
1744 Errors on associated ``localCalib`` values. Ignored and deprecated;
1745 will be removed after v29.
1749 calibFluxErr : `~numpy.ndarray` or `~pandas.Series`
1750 Errors on calibrated flux measurements.
1753 if localCalibErr
is not None:
1754 warnings.warn(
"The localCalibErr argument is deprecated and will be removed after v29.",
1755 category=FutureWarning)
1756 return instFluxErr * localCalib
1759 """Convert instrument flux to nanojanskys.
1763 instFlux : `~numpy.ndarray` or `~pandas.Series`
1764 Array of instrument flux measurements.
1765 localCalib : `~numpy.ndarray` or `~pandas.Series`
1766 Array of local photometric calibration estimates.
1770 calibMag : `~numpy.ndarray` or `~pandas.Series`
1771 Array of calibrated AB magnitudes.
1776 """Convert instrument flux err to nanojanskys.
1780 instFlux : `~numpy.ndarray` or `~pandas.Series`
1781 Array of instrument flux measurements.
1782 instFluxErr : `~numpy.ndarray` or `~pandas.Series`
1783 Errors on associated ``instFlux`` values.
1784 localCalib : `~numpy.ndarray` or `~pandas.Series`
1785 Array of local photometric calibration estimates.
1786 localCalibErr : `~numpy.ndarray` or `~pandas.Series`, optional
1787 Errors on associated ``localCalib`` values. Ignored and deprecated;
1788 will be removed after v29.
1792 calibMagErr: `~numpy.ndarray` or `~pandas.Series`
1793 Error on calibrated AB magnitudes.
1796 if localCalibErr
is not None:
1797 warnings.warn(
"The localCalibErr argument is deprecated and will be removed after v29.",
1798 category=FutureWarning)
1804 """Compute calibrated fluxes using the local calibration value.
1806 This returns units of nanojanskys.
1815 return f
'flux_{self.instFluxCol}'
1823 """Compute calibrated flux errors using the local calibration value.
1825 This returns units of nanojanskys.
1834 return f
'fluxErr_{self.instFluxCol}'
1842 """Compute absolute mean of dipole fluxes.
1848 LocalDipoleMeanFluxErr
1850 LocalDipoleDiffFluxErr
1859 photoCalibErrCol=None,
1880 return f
'dipMeanFlux_{self.instFluxPosCol}_{self.instFluxNegCol}'
1888 """Compute the error on the absolute mean of dipole fluxes.
1896 LocalDipoleDiffFluxErr
1909 return f
'dipMeanFluxErr_{self.instFluxPosCol}_{self.instFluxNegCol}'
1916 """Compute the absolute difference of dipole fluxes.
1918 Calculated value is (abs(pos) - abs(neg)).
1925 LocalDipoleMeanFluxErr
1926 LocalDipoleDiffFluxErr
1937 return f
'dipDiffFlux_{self.instFluxPosCol}_{self.instFluxNegCol}'
1945 """Compute the error on the absolute difference of dipole fluxes.
1952 LocalDipoleMeanFluxErr
1966 return f
'dipDiffFluxErr_{self.instFluxPosCol}_{self.instFluxNegCol}'
1973 """Compute E(B-V) from dustmaps.sfd."""
1974 _defaultDataset =
'ref'
1981 with open(os.devnull,
"w")
as devnull:
1982 with redirect_stdout(devnull):
1983 from dustmaps.sfd
import SFDQuery
1989 coords = SkyCoord(df[
'coord_ra'].values * u.rad, df[
'coord_dec'].values * u.rad)
1990 ebv = self.
sfd(coords)
1991 return pd.Series(ebv, index=df.index).astype(
'float32')
1995 """Base class for functors that use shape moments and localWCS
1999 is_covariance : bool
2000 Whether the shape columns are terms of a covariance matrix. If False,
2001 they will be assumed to be terms of a correlation matrix instead.
2004 is_covariance: bool =
True
2034 """Return columns that are needed from the ref table."""
2042 r"""Return terms commonly used for ellipse parameterization conversions.
2049 Whether to compute the terms in sky coordinates.
2050 If False, XX, YY and XY moments are used instead of
2056 The sum of the diagonal terms of the covariance.
2058 The difference of the diagonal terms of the covariance.
2060 A term similar to the discriminant of the quadratic formula.
2065 t2 = xx_m_yy**2 + 4.0*(self.
sky_uv(df)
if sky
else self.
get_xy(df))**2
2069 return xx + yy, xx_m_yy, t2
2086 """Return the component of the moments tensor aligned with the RA axis, in radians."""
2092 return (CD_1_1*(i_xx*CD_1_1 + i_xy*CD_1_2)
2093 + CD_1_2*(i_xy*CD_1_1 + i_yy*CD_1_2))
2096 """Return the component of the moments tensor aligned with the dec axis, in radians."""
2102 return (CD_2_1*(i_xx*CD_2_1 + i_xy*CD_2_2)
2103 + CD_2_2*(i_xy*CD_2_1 + i_yy*CD_2_2))
2106 """Return the covariance of the moments tensor in ra, dec coordinates, in radians."""
2114 return ((CD_1_1 * i_xx + CD_1_2 * i_xy) * CD_2_1
2115 + (CD_1_1 * i_xy + CD_1_2 * i_yy) * CD_2_2)
2119 Calculate shear-type ellipticity parameter G1.
2125 denom = sky_uu + sky_vv + 2 * np.sqrt(sky_uu*sky_vv - sky_uv**2)
2126 return ((sky_uu - sky_vv) / denom).astype(np.float32)
2130 Calculate shear-type ellipticity parameter G2.
2132 This has the opposite sign as sky_uv in order to maintain consistency with the HSM moments
2139 denom = sky_uu + sky_vv + 2 * np.sqrt(sky_uu*sky_vv - sky_uv**2)
2140 return (-2*sky_uv / denom).astype(np.float32)
2145 return np.sqrt(0.5*(sky_uu + sky_vv)).astype(np.float32)
2149 """Rotate pixel moments Ixx,Iyy,Ixy into RA/dec frame and G1/G2 reduced
2150 shear parameterization"""
2151 _defaultDataset =
'meas'
2153 shortname =
"moments_g1"
2158 return pd.Series(sky_g1.astype(np.float32), index=df.index)
2162 """Rotate pixel moments Ixx,Iyy,Ixy into RA/dec frame and G1/G2 reduced
2163 shear parameterization"""
2164 _defaultDataset =
'meas'
2166 shortname =
"moments_g2"
2171 return pd.Series(sky_g2.astype(np.float32), index=df.index)
2175 """Trace radius size in arcseconds from pixel moments Ixx,Iyy,Ixy
2177 The trace radius size is a measure of size equal to the square root of
2178 half of the trace of the second moments tensor.
2180 _defaultDataset =
'meas'
2181 name =
"moments_trace"
2182 shortname =
"moments_trace"
2187 return pd.Series((sky_trace_radians*(180/np.pi)*3600).astype(np.float32), index=df.index)
2191 """Rotate pixel moments Ixx,Iyy,Ixy into ra,dec frame and arcseconds"""
2192 _defaultDataset =
'meas'
2194 shortname =
"moments_uu"
2197 sky_uu_radians = self.
sky_uu(df)
2199 return pd.Series((sky_uu_radians*((180/np.pi)*3600)**2).astype(np.float32), index=df.index)
2203 """MomentsIuuSky but from sigma_x, sigma_y, rho correlation terms."""
2204 is_covariance =
False
2208 """Rotate pixel moments Ixx,Iyy,Ixy into ra,dec frame and arcseconds"""
2209 _defaultDataset =
'meas'
2211 shortname =
"moments_vv"
2214 sky_vv_radians = self.
sky_vv(df)
2216 return pd.Series((sky_vv_radians*((180/np.pi)*3600)**2).astype(np.float32), index=df.index)
2220 """MomentsIvvSky but from sigma_x, sigma_y, rho correlation terms."""
2221 is_covariance =
False
2225 """Rotate pixel moments Ixx,Iyy,Ixy into ra,dec frame and arcseconds"""
2226 _defaultDataset =
'meas'
2228 shortname =
"moments_uv"
2231 sky_uv_radians = self.
sky_uv(df)
2233 return pd.Series((sky_uv_radians*((180/np.pi)*3600)**2).astype(np.float32), index=df.index)
2237 """MomentsIuvSky but from sigma_x, sigma_y, rho correlation terms."""
2238 is_covariance =
False
2242 """Compute position angle relative to ra,dec frame, in degrees, from Ixx,Iyy,Ixy pixel moments."""
2243 _defaultDataset =
'meas'
2244 name =
"moments_theta"
2245 shortname =
"moments_theta"
2251 theta = 0.5*np.arctan2(2*sky_uv, sky_uu - sky_vv)
2253 return pd.Series((np.degrees(np.array(theta))).astype(np.float32), index=df.index)
2257 """PositionAngleFromMoments but from sigma_x, sigma_y, rho correlation terms."""
2258 is_covariance =
False
2262 """Compute the semimajor axis length in arcseconds, from Ixx,Iyy,Ixy pixel moments."""
2263 _defaultDataset =
'meas'
2265 shortname =
"moments_a"
2270 a_radians = np.sqrt(0.5 * (xx_p_yy + np.sqrt(t2)))
2272 return pd.Series((np.degrees(a_radians)*3600).astype(np.float32), index=df.index)
2276 """SemimajorAxisFromMoments but from sigma_x, sigma_y, rho correlation terms."""
2277 is_covariance =
False
2281 """Compute the semiminor axis length in arcseconds, from Ixx,Iyy,Ixy pixel moments."""
2282 _defaultDataset =
'meas'
2284 shortname =
"moments_b"
2289 b_radians = np.sqrt(0.5 * (xx_p_yy - np.sqrt(t2)))
2291 return pd.Series((np.degrees(b_radians)*3600).astype(np.float32), index=df.index)
2295 """SemiminorAxisFromMoments but from sigma_x, sigma_y, rho correlation terms."""
2296 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_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)