You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Some of the multi-passband class constructs will require the prior information about passbands.
An example is temporial-spectral model fits (e.g. some generalization of BazinFit) which need to know effective wavelengths of pass-throughs of the filters.
Even simpler example is the color of medians which needs to know the order of filters: g-r or r-g.
If we require passband list for class initialization for all features, it would give us a benefit to prepare the ordered lists for .names and .descriptions attributes like we have now.
However giving passbands in advance could be annoying for the user, especially in the cases when output doesn't depend on count of the passbands or their properties (for instance for multicolor periodogram).
__call__ signature
It looks like the most popular data format for multi-color light curves is columnar - t, m, sigma, band are separate columns, while band encodes passband with a string.
The support of this format is straightforward, but the signature of the extraction functions is not.
The simple way is to just making it __call__(t, m, sigma, band), but this makes sigma mandatory even if it is not necessary / needed by the function.
Any other order would confuse a user, because it would be different from what we have currently (btw __call__(band, t, m, sigma=None) could work, but it is not how people order things usually, right?).
Another option is to make something like __call__(t, m, sigma=None, *, band).
It is not super-intuitive, but could work too.
Before going to the last option let's discuss another possible data representation: a dictionary of single-band light curves: {band: (t, m, sigma=None), ...}.
We can make a simple function to convert this representation to columnar-based, but some features could work faster with one representation than another.
It leads us to "flexible" interface.
__call__(t=None, m=None, sigma=None, band=None, *, data=None, columns=("t", "m", "sigma", "band")) could be used and data could be everything:
{band: (t, m, sigma)} or {band: (t, m)},
iterable yielding single observations (t, m, sigma, band) or (t, m, band) or (band, t, m, sigma) or ..., where band position will be detected by its string type,
(t, m, sigma, band) or (t, m, band) or (band, t, m) or ..., where each value is an array, band is determined by its dtype,
pandas.Dataframe or astropy.table.Table or {t: [], m: [], sigma: [], band: []}, column/key names are given by columns keyword argument.
t, m, sigma, band are used in a simple way: if no data is given then t, m and band must present, while sigma is still optional.
How to change current single-passband interface
It would be nice to handle the current interface for backward compatibility.
Initialization
If we will decide to make passband information mandatory for multicolor feature constructors, then we could add an optional passband list argument to all single-band features.
The non-None value of this argument would "transform" a feature from being single-band to multi-band (we can even do it via __new__ and choose a variant inherited from a different base class) changing .names and .descriptions accordingly.
__call__ and many
Choice of the __call__ signature depends on what we will use for multi-color features.
The obvious backward-compatible option is __call__(t, m, sigma=None, band=None).
This could work even if we don't add the band list argument to the constructor, but causes questions about the return value.
In the case when passband list is given in advance, .names and .descriptions are defined, we could just stack feature values in the order of passbands, for example for two-feature extractor and a set of two features we will have [f1_band1, f2_band1, f1_band2, f2_band2].
In the opposite case, it is not clear what the order of the passbands should be, because our feature extractor sees the bands first time at the method call.
I think the only right way in this case is returning a dictionary {band1: [f1_band1, f2_band1], band2: [f1_band2, f2_band2]}, but it would cause additional cost for a user to parse this value.
many would reflect all other choices we make in some way =)
Example from other packages
LINCC TAPE uses TimeSeries class as public interface. I would try maing things more flexible and do not introduce a new wrapper class.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
We need a support of multi-passband features.
The main work happens at https://github.com/light-curve/light-curve-feature, but here we should think how to implement the Python interface.
Design issues and ideas
Multi-passband feature extractors
Initialization
Some of the multi-passband class constructs will require the prior information about passbands.
An example is temporial-spectral model fits (e.g. some generalization of
BazinFit
) which need to know effective wavelengths of pass-throughs of the filters.Even simpler example is the color of medians which needs to know the order of filters: g-r or r-g.
If we require passband list for class initialization for all features, it would give us a benefit to prepare the ordered lists for
.names
and.descriptions
attributes like we have now.However giving passbands in advance could be annoying for the user, especially in the cases when output doesn't depend on count of the passbands or their properties (for instance for multicolor periodogram).
__call__
signatureIt looks like the most popular data format for multi-color light curves is columnar -
t
,m
,sigma
,band
are separate columns, whileband
encodes passband with a string.The support of this format is straightforward, but the signature of the extraction functions is not.
The simple way is to just making it
__call__(t, m, sigma, band)
, but this makessigma
mandatory even if it is not necessary / needed by the function.Any other order would confuse a user, because it would be different from what we have currently (btw
__call__(band, t, m, sigma=None)
could work, but it is not how people order things usually, right?).Another option is to make something like
__call__(t, m, sigma=None, *, band)
.It is not super-intuitive, but could work too.
Before going to the last option let's discuss another possible data representation: a dictionary of single-band light curves:
{band: (t, m, sigma=None), ...}
.We can make a simple function to convert this representation to columnar-based, but some features could work faster with one representation than another.
It leads us to "flexible" interface.
__call__(t=None, m=None, sigma=None, band=None, *, data=None, columns=("t", "m", "sigma", "band"))
could be used anddata
could be everything:{band: (t, m, sigma)}
or{band: (t, m)}
,(t, m, sigma, band)
or(t, m, band)
or(band, t, m, sigma)
or...
, where band position will be detected by its string type,(t, m, sigma, band)
or(t, m, band)
or(band, t, m)
or...
, where each value is an array,band
is determined by its dtype,pandas.Dataframe
orastropy.table.Table
or {t: [], m: [], sigma: [], band: []}, column/key names are given bycolumns
keyword argument.t
,m
,sigma
,band
are used in a simple way: if nodata
is given thent
,m
andband
must present, whilesigma
is still optional.How to change current single-passband interface
It would be nice to handle the current interface for backward compatibility.
Initialization
If we will decide to make passband information mandatory for multicolor feature constructors, then we could add an optional passband list argument to all single-band features.
The non-None value of this argument would "transform" a feature from being single-band to multi-band (we can even do it via
__new__
and choose a variant inherited from a different base class) changing.names
and.descriptions
accordingly.__call__
andmany
Choice of the
__call__
signature depends on what we will use for multi-color features.The obvious backward-compatible option is
__call__(t, m, sigma=None, band=None)
.This could work even if we don't add the band list argument to the constructor, but causes questions about the return value.
In the case when passband list is given in advance,
.names
and.descriptions
are defined, we could just stack feature values in the order of passbands, for example for two-feature extractor and a set of two features we will have[f1_band1, f2_band1, f1_band2, f2_band2]
.In the opposite case, it is not clear what the order of the passbands should be, because our feature extractor sees the bands first time at the method call.
I think the only right way in this case is returning a dictionary
{band1: [f1_band1, f2_band1], band2: [f1_band2, f2_band2]}
, but it would cause additional cost for a user to parse this value.many
would reflect all other choices we make in some way =)Example from other packages
TAPE
usesTimeSeries
class as public interface. I would try maing things more flexible and do not introduce a new wrapper class.Beta Was this translation helpful? Give feedback.
All reactions