LSST Applications g07dc498a13+cb17356775,g1409bbee79+cb17356775,g1a7e361dbc+cb17356775,g1fd858c14a+d1a2a640a9,g33399d78f5+fe6948661d,g35bb328faa+e55fef2c71,g3bd4b5ce2c+cac9e18807,g3c79e8cd92+2359a18b76,g43bc871e57+a58ba40925,g53246c7159+e55fef2c71,g60b5630c4e+8133a3545f,g78460c75b0+8427c4cc8f,g78619a8342+55305cb8f0,g786e29fd12+307f82e6af,g8534526c7b+8e1c6b434f,g89139ef638+cb17356775,g8b49a6ea8e+8133a3545f,g8ffcb69f3d+818ab6c36e,g9125e01d80+e55fef2c71,g97b8272a79+98425f45f6,g989de1cb63+cb17356775,g9f33ca652e+4245ceb508,gaaedd4e678+cb17356775,gabe3b4be73+9c0c3c7524,gb1101e3267+3e5ef1d639,gb58c049af0+28045f66fd,gc1fe0db326+8133a3545f,gca43fec769+e55fef2c71,gcf25f946ba+fe6948661d,gd397e13551+64039f84ea,gd6cbbdb0b4+f6e5445f66,gde0f65d7ad+7eb368c542,ge278dab8ac+b4c2c8faf7,geab183fbe5+8133a3545f,gecb8035dfe+1f480bec5e,gefa07fa684+e7bc33f3ea,gf58bf46354+e55fef2c71,gfe7187db8c+e55afb4430,w.2025.03
LSST Data Management Base Package
Loading...
Searching...
No Matches
lsst.pipe.tasks.functors.CompositeFunctor Class Reference
Inheritance diagram for lsst.pipe.tasks.functors.CompositeFunctor:
lsst.pipe.tasks.functors.Functor

Public Member Functions

 __init__ (self, funcs, **kwargs)
 
 filt (self)
 
 filt (self, filt)
 
 update (self, new)
 
 columns (self)
 
 multilevelColumns (self, data, **kwargs)
 
 __call__ (self, data, **kwargs)
 
 renameCol (cls, col, renameRules)
 
 from_file (cls, filename, **kwargs)
 
 from_yaml (cls, translationDefinition, **kwargs)
 

Public Attributes

 funcDict
 
 filt
 
 name
 

Static Public Attributes

 dataset = None
 
str name = "CompositeFunctor"
 

Protected Attributes

 _filt
 

Detailed Description

Perform multiple calculations at once on a catalog.

The role of a `CompositeFunctor` is to group together computations from
multiple functors.
Instead of returning `~pandas.Series` a `CompositeFunctor` returns a
`~pandas.DataFrame`, with the column names being the keys of ``funcDict``.

The `columns` attribute of a `CompositeFunctor` is the union of all columns
in all the component functors.

A `CompositeFunctor` does not use a `_func` method itself; rather, when a
`CompositeFunctor` is called, all its columns are loaded at once, and the
resulting DataFrame is passed to the `_func` method of each component
functor.
This has the advantage of only doing I/O (reading from parquet file) once,
and works because each individual `_func` method of each component functor
does not care if there are *extra* columns in the DataFrame being passed;
only that it must contain *at least* the `columns` it expects.

An important and useful class method is `from_yaml`, which takes as an
argument the path to a YAML file specifying a collection of functors.

Parameters
----------
funcs : `dict` or `list`
    Dictionary or list of functors.
    If a list, then it will be converted into a dictonary according to the
    `.shortname` attribute of each functor.

Definition at line 380 of file functors.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.pipe.tasks.functors.CompositeFunctor.__init__ ( self,
funcs,
** kwargs )

Reimplemented from lsst.pipe.tasks.functors.Functor.

Definition at line 413 of file functors.py.

413 def __init__(self, funcs, **kwargs):
414
415 if type(funcs) is dict:
416 self.funcDict = funcs
417 else:
418 self.funcDict = {f.shortname: f for f in funcs}
419
420 self._filt = None
421
422 super().__init__(**kwargs)
423

Member Function Documentation

◆ __call__()

lsst.pipe.tasks.functors.CompositeFunctor.__call__ ( self,
data,
** kwargs )
Apply the functor to the data table.

Parameters
----------
data : various
    The data represented as `~lsst.daf.butler.DeferredDatasetHandle`,
    `~lsst.pipe.base.InMemoryDatasetHandle`, or `~pandas.DataFrame`.
    The table or a pointer to a table on disk from which columns can
    be accessed.

Reimplemented from lsst.pipe.tasks.functors.Functor.

Definition at line 467 of file functors.py.

467 def __call__(self, data, **kwargs):
468 """Apply the functor to the data table.
469
470 Parameters
471 ----------
472 data : various
473 The data represented as `~lsst.daf.butler.DeferredDatasetHandle`,
474 `~lsst.pipe.base.InMemoryDatasetHandle`, or `~pandas.DataFrame`.
475 The table or a pointer to a table on disk from which columns can
476 be accessed.
477 """
478 if isinstance(data, pd.DataFrame):
479 _data = InMemoryDatasetHandle(data, storageClass="DataFrame")
480 elif isinstance(data, (DeferredDatasetHandle, InMemoryDatasetHandle)):
481 _data = data
482 else:
483 raise RuntimeError(f"Unexpected type provided for data. Got {get_full_type_name(data)}.")
484
485 columnIndex = self._get_columnIndex(_data)
486
487 if isinstance(columnIndex, pd.MultiIndex):
488 columns = self.multilevelColumns(_data, columnIndex=columnIndex)
489 df = _data.get(parameters={"columns": columns})
490
491 valDict = {}
492 for k, f in self.funcDict.items():
493 try:
494 subdf = f._setLevels(
495 df[f.multilevelColumns(_data, returnTuple=True, columnIndex=columnIndex)]
496 )
497 valDict[k] = f._func(subdf)
498 except Exception as e:
499 self.log.exception(
500 "Exception in %s (funcs: %s) call: %s",
501 self.name,
502 str(list(self.funcDict.keys())),
503 type(e).__name__,
504 )
505 try:
506 valDict[k] = f.fail(subdf)
507 except NameError:
508 raise e
509
510 else:
511 df = _data.get(parameters={"columns": self.columns})
512
513 valDict = {k: f._func(df) for k, f in self.funcDict.items()}
514
515 # Check that output columns are actually columns.
516 for name, colVal in valDict.items():
517 if len(colVal.shape) != 1:
518 raise RuntimeError("Transformed column '%s' is not the shape of a column. "
519 "It is shaped %s and type %s." % (name, colVal.shape, type(colVal)))
520
521 try:
522 valDf = pd.concat(valDict, axis=1)
523 except TypeError:
524 print([(k, type(v)) for k, v in valDict.items()])
525 raise
526
527 if kwargs.get('dropna', False):
528 valDf = valDf.dropna(how='any')
529
530 return valDf
531
std::vector< SchemaItem< Flag > > * items

◆ columns()

lsst.pipe.tasks.functors.CompositeFunctor.columns ( self)
Columns required to perform calculation.

Reimplemented from lsst.pipe.tasks.functors.Functor.

Definition at line 449 of file functors.py.

449 def columns(self):
450 return list(set([x for y in [f.columns for f in self.funcDict.values()] for x in y]))
451

◆ filt() [1/2]

lsst.pipe.tasks.functors.CompositeFunctor.filt ( self)

Reimplemented from lsst.pipe.tasks.functors.Functor.

Definition at line 425 of file functors.py.

425 def filt(self):
426 return self._filt
427

◆ filt() [2/2]

lsst.pipe.tasks.functors.CompositeFunctor.filt ( self,
filt )

Reimplemented from lsst.pipe.tasks.functors.Functor.

Definition at line 429 of file functors.py.

429 def filt(self, filt):
430 if filt is not None:
431 for _, f in self.funcDict.items():
432 f.filt = filt
433 self._filt = filt
434

◆ from_file()

lsst.pipe.tasks.functors.CompositeFunctor.from_file ( cls,
filename,
** kwargs )

Definition at line 542 of file functors.py.

542 def from_file(cls, filename, **kwargs):
543 # Allow environment variables in the filename.
544 filename = os.path.expandvars(filename)
545 with open(filename) as f:
546 translationDefinition = yaml.safe_load(f)
547
548 return cls.from_yaml(translationDefinition, **kwargs)
549

◆ from_yaml()

lsst.pipe.tasks.functors.CompositeFunctor.from_yaml ( cls,
translationDefinition,
** kwargs )

Definition at line 551 of file functors.py.

551 def from_yaml(cls, translationDefinition, **kwargs):
552 funcs = {}
553 for func, val in translationDefinition['funcs'].items():
554 funcs[func] = init_fromDict(val, name=func)
555
556 if 'flag_rename_rules' in translationDefinition:
557 renameRules = translationDefinition['flag_rename_rules']
558 else:
559 renameRules = None
560
561 if 'calexpFlags' in translationDefinition:
562 for flag in translationDefinition['calexpFlags']:
563 funcs[cls.renameCol(flag, renameRules)] = Column(flag, dataset='calexp')
564
565 if 'refFlags' in translationDefinition:
566 for flag in translationDefinition['refFlags']:
567 funcs[cls.renameCol(flag, renameRules)] = Column(flag, dataset='ref')
568
569 if 'forcedFlags' in translationDefinition:
570 for flag in translationDefinition['forcedFlags']:
571 funcs[cls.renameCol(flag, renameRules)] = Column(flag, dataset='forced_src')
572
573 if 'flags' in translationDefinition:
574 for flag in translationDefinition['flags']:
575 funcs[cls.renameCol(flag, renameRules)] = Column(flag, dataset='meas')
576
577 return cls(funcs, **kwargs)
578
579

◆ multilevelColumns()

lsst.pipe.tasks.functors.CompositeFunctor.multilevelColumns ( self,
data,
** columnIndex )
Returns columns needed by functor from multilevel dataset.

To access tables with multilevel column structure, the
`~lsst.daf.butler.DeferredDatasetHandle` or
`~lsst.pipe.base.InMemoryDatasetHandle` needs to be passed
either a list of tuples or a dictionary.

Parameters
----------
data : various
    The data as either `~lsst.daf.butler.DeferredDatasetHandle`, or
    `~lsst.pipe.base.InMemoryDatasetHandle`.
columnIndex (optional): pandas `~pandas.Index` object
    Either passed or read in from
    `~lsst.daf.butler.DeferredDatasetHandle`.
`returnTuple` : `bool`
    If true, then return a list of tuples rather than the column
    dictionary specification.
    This is set to `True` by `CompositeFunctor` in order to be able to
    combine columns from the various component functors.

Reimplemented from lsst.pipe.tasks.functors.Functor.

Definition at line 452 of file functors.py.

452 def multilevelColumns(self, data, **kwargs):
453 # Get the union of columns for all component functors.
454 # Note the need to have `returnTuple=True` here.
455 return list(
456 set(
457 [
458 x
459 for y in [
460 f.multilevelColumns(data, returnTuple=True, **kwargs) for f in self.funcDict.values()
461 ]
462 for x in y
463 ]
464 )
465 )
466

◆ renameCol()

lsst.pipe.tasks.functors.CompositeFunctor.renameCol ( cls,
col,
renameRules )

Definition at line 533 of file functors.py.

533 def renameCol(cls, col, renameRules):
534 if renameRules is None:
535 return col
536 for old, new in renameRules:
537 if col.startswith(old):
538 col = col.replace(old, new)
539 return col
540

◆ update()

lsst.pipe.tasks.functors.CompositeFunctor.update ( self,
new )
Update the functor with new functors.

Definition at line 435 of file functors.py.

435 def update(self, new):
436 """Update the functor with new functors."""
437 if isinstance(new, dict):
438 self.funcDict.update(new)
439 elif isinstance(new, CompositeFunctor):
440 self.funcDict.update(new.funcDict)
441 else:
442 raise TypeError('Can only update with dictionary or CompositeFunctor.')
443
444 # Make sure new functors have the same 'filt' set.
445 if self.filt is not None:
446 self.filt = self.filt
447

Member Data Documentation

◆ _filt

lsst.pipe.tasks.functors.CompositeFunctor._filt
protected

Definition at line 420 of file functors.py.

◆ dataset

lsst.pipe.tasks.functors.CompositeFunctor.dataset = None
static

Definition at line 410 of file functors.py.

◆ filt

lsst.pipe.tasks.functors.CompositeFunctor.filt

Definition at line 446 of file functors.py.

◆ funcDict

lsst.pipe.tasks.functors.CompositeFunctor.funcDict

Definition at line 416 of file functors.py.

◆ name [1/2]

str lsst.pipe.tasks.functors.CompositeFunctor.name = "CompositeFunctor"
static

Definition at line 411 of file functors.py.

◆ name [2/2]

lsst.pipe.tasks.functors.CompositeFunctor.name

Definition at line 501 of file functors.py.


The documentation for this class was generated from the following file: