Skip to content

litmus.lightcurve

Bases: object

A wrapper class for lightcurves. Construct /w array-like inputs for time, signal and error (optional) like: lightcurve(T, Y, E) or: lightcurve(T, Y) Which yields E=0 for all {T,Y}

Supports array-like addition and float-like addition / multiplication

Source code in litmus/lightcurve.py
38
39
40
41
42
43
44
45
46
47
48
49
def __init__(self, T, Y, E=None):
    self.T = np.array(T, dtype=np.float64)
    self.Y = np.array(Y, dtype=np.float64)
    if E is None:
        self.E = np.zeros_like(T)
    else:
        self.E = E

    self._data = np.vstack(self.values()).T

    self._norm_mean, self._norm_amp = 0.0, 1.0
    self.normalized = False

T = np.array(T, dtype=np.float64) instance-attribute

Y = np.array(Y, dtype=np.float64) instance-attribute

E = np.zeros_like(T) instance-attribute

normalized = False instance-attribute

keys() -> [str, str, str]

Returns the string-like names of the lightcurve's attributes

Source code in litmus/lightcurve.py
120
121
122
123
124
def keys(self) -> [str, str, str]:
    """
    Returns the string-like names of the lightcurve's attributes
    """
    return ["T", "Y", "E"]

values() -> (_types.ArrayN, _types.ArrayN, _types.ArrayN)

Returns the lightcurves' value series' in the order of keys

Source code in litmus/lightcurve.py
126
127
128
129
130
def values(self) -> (_types.ArrayN, _types.ArrayN, _types.ArrayN):
    """
    Returns the lightcurves' value series' in the order of keys
    """
    return [self[key] for key in self.keys()]

normalize() -> _types.Self

Esimates the mean and amplitude of the lighturve assuming uncorrelated measurements Returns a lightcurve object with this normalization

Source code in litmus/lightcurve.py
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
def normalize(self) -> _types.Self:
    """
    Esimates the mean and amplitude of the lighturve assuming uncorrelated measurements
    Returns a lightcurve object with this normalization
    """

    if self.normalized: return self

    # Check if have errorbars
    no_errs = False
    E = self.E
    if max(E)== 0:
        no_errs = True
        E = np.ones_like(self.E)

    # Get initial guess assuming no scatter
    w = E ** -2
    mean0 = np.average(self.Y, weights=w)
    var0 = np.average((self.Y - mean0) ** 2, weights=w)

    if no_errs:
        meanbest, varbest = mean0, var0
    else:
        L = lambda X: ((self.Y - X[0]) ** 2 / (self.E ** 2 + X[1]) + np.log(self.E ** 2 + X[1])).sum()
        meanbest, varbest = optimize.minimize(L, np.array([mean0, var0]), method='Nelder-Mead').x

    # Make and return copy
    out = copy(self)
    out -= meanbest
    out /= np.sqrt(varbest)

    # If any errors, revert to simple estiamte
    if np.any(np.isnan(out._data)):
        meanbest, varbest = mean0, var0
        out = copy(self)
        out -= meanbest
        out /= np.sqrt(varbest)

    # Store normalizing values for later
    out._norm_mean = meanbest
    out._norm_amp = np.sqrt(varbest)

    out.normalized = True

    return out

unnormalize() -> _types.Self

Reverses the effects of lightcurve.normalize(). Returns a lightcurve object with mean and amplitude prior to normalize()

Source code in litmus/lightcurve.py
193
194
195
196
197
198
199
200
201
202
203
204
def unnormalize(self) -> _types.Self:
    """
    Reverses the effects of lightcurve.normalize().
    Returns a lightcurve object with mean and amplitude prior to normalize()
    """
    out = copy(self)
    out *= self._norm_amp
    out += self._norm_mean
    out._norm_amp = 1.0
    out._norm_mean = 0.0
    out.normalized = False
    return out

delayed_copy(lag=0.0, Tmin=None, Tmax=None) -> _types.Self

Returns a copy subsampled to only datapoints in the domain T in [Tmin,Tmax] and offset by lag

Source code in litmus/lightcurve.py
206
207
208
209
210
211
212
213
214
215
216
217
def delayed_copy(self, lag=0.0, Tmin=None, Tmax=None) -> _types.Self:
    """
    Returns a copy subsampled to only datapoints in the domain T in [Tmin,Tmax] and offset by lag
    """
    if Tmin is None: Tmin = self.T.min()
    if Tmax is None: Tmax = self.T.max()
    I = np.where((self.T + lag > Tmin) * (self.T + lag < Tmax))[0]

    return (lightcurve(T=self.T[I] + lag,
                       Y=self.Y[I],
                       E=self.E[I]
                       ))

trimmed_copy(Tmin=None, Tmax=None) -> _types.Self

Returns a copy subsampled to only datapoints in the domain T in [Tmin,Tmax]

Source code in litmus/lightcurve.py
219
220
221
222
223
def trimmed_copy(self, Tmin=None, Tmax=None) -> _types.Self:
    """
    Returns a copy subsampled to only datapoints in the domain T in [Tmin,Tmax]
    """
    return self.delayed_copy(0, Tmin, Tmax)

plot(axis=None, show=True, **kwargs) -> None

Plots an errorbar series to a matplotlib axis. If show=True, will plt.show() after plotting. If axis is None, will create a new figure. Pass in any plotting kwargs for plt.errorbar at **kwargs

Source code in litmus/lightcurve.py
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
def plot(self, axis=None, show=True, **kwargs) -> None:
    """
    Plots an errorbar series to a matplotlib axis.
    If show=True, will plt.show() after plotting.
    If axis is None, will create a new figure.
    Pass in any plotting kwargs for plt.errorbar at **kwargs
    """
    if axis is None:
        plt.figure()
        axis = plt.gca()
        axis.set_xlabel("T")
        axis.set_Ylabel("Y")
    axis.errorbar(self.T, self.Y, self.E, fmt='none', **kwargs)

    if show: plt.show()

copy()

Source code in litmus/lightcurve.py
250
251
def copy(self):
    return copy(self)