Skip to content

Commit 219cfb5

Browse files
committed
Merge branch 'devel'
2 parents 5d95178 + 2986078 commit 219cfb5

File tree

7 files changed

+308
-31
lines changed

7 files changed

+308
-31
lines changed

.travis.yml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,27 @@ jobs:
2222

2323
# command to install dependencies
2424
install:
25-
- pip install -r requirements.txt
25+
- pip install --upgrade pip
26+
- pip uninstall numpy Bottleneck -y
27+
- pip install numpy==1.15.4 --no-cache-dir
28+
- pip install -r requirements.txt --no-cache-dir
2629
script:
2730
- pytest
2831
branches:
2932
only:
3033
- master
31-
- devel
34+
- devel
35+
- /^v\d+\.\d+.+$/
36+
37+
# Deploy to GitHub Releases, making a release of the
38+
# code whenever a new tag is added on the master branch
39+
deploy:
40+
provider: releases
41+
api_key: $GITHUB_TOKEN
42+
skip_cleanup: true
43+
draft: true
44+
on:
45+
branch:
46+
- master
47+
- /^v\d+\.\d+.+$/
48+
tags: true

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
master-v0.1
1+
master-v1.0.9

corrections/cbv_corrector/GOC_code.py

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import os
1010
import numpy as np
11+
import math as m
1112
import logging
1213
from tqdm import tqdm
1314
from bottleneck import nanmean, nanmedian
@@ -17,23 +18,105 @@
1718
import six
1819
from lightkurve import TessLightCurve
1920
from astropy.io import fits
20-
21+
from astropy.stats import LombScargle
2122

2223
from .cbv_main import lc_matrix_calc
2324
from ..plots import plt
2425
from ..quality import CorrectorQualityFlags, TESSQualityFlags
25-
from .manual_filters import manual_exclude
26+
from ..manual_filters import manual_exclude
27+
28+
import matplotlib.pyplot as pl
2629

2730
# =============================================================================
2831
#
2932
# =============================================================================
3033

31-
def wn(ori_flux, corrected_flux):
32-
"""Calculate added white nosie between two light curves"""
34+
def psd_scargle(time, flux, Nsample = 10.):
35+
"""
36+
Calculate the power spectral density using the Lomb-Scargle (L-S) periodogram
37+
38+
Parameters:
39+
time (numpy array, float): time stamps of the light curve
40+
flux (numpy array, float): the flux variations of the light curve
41+
Nsample (optional, float): oversampling rate for the periodogram. Default value = 10.
42+
43+
Returns:
44+
fr (numpy array, float): evaluated frequency values in the domain of the periodogram
45+
sc (numpy array, float): the PSD values of the L-S periodogram
46+
47+
.. codeauthor:: Timothy Van Reeth <timothy.vanreeth@kuleuven.be>
48+
"""
49+
ndata = len(time) # The number of data points
50+
fnyq = 0.5/np.median(time[1:]-time[:-1]) # the Nyquist frequency
51+
fres = 1./(time[-1]-time[0]) # the frequency resolution
52+
fr = np.arange(0.,fnyq,fres/float(Nsample)) # the frequencies
53+
sc1 = LombScargle(time, flux).power(fr, normalization='psd') # The non-normalized Lomb-Scargle "power"
54+
55+
# Computing the appropriate rescaling factors (to convert to astrophysical units)
56+
fct = m.sqrt(4./ndata)
57+
T = time.ptp()
58+
sc = fct**2. * sc1 * T
59+
60+
# Ensuring the output does not contain nans
61+
if(np.isnan(sc).any()):
62+
fr = fr[~np.isnan(sc)]
63+
sc = sc[~np.isnan(sc)]
64+
65+
return fr, sc
66+
67+
68+
69+
def wn(ori_lc, corrected_lc, alpha_n = 1.):
70+
"""
71+
Calculate added white noise between two light curves.
72+
Based on Eq. 8.4-8.5 in the Kepler PDC
73+
74+
Parameters:
75+
ori_lc (light kurve object): the uncorrected TESS light curve
76+
corrected_lc (light kurve object): the corrected TESS light curve
77+
alpha_n (optional, float): scaling factor. Default value = 1.
78+
79+
Returns:
80+
Gn (float): goodness metric for the added white noise.
81+
In the limit where ori_lc and corrected_lc are identical, Gn approaches 0.
82+
In the (improbable?) case where noise is removed instead of added, Gn = -1.
83+
84+
85+
.. codeauthor:: Timothy Van Reeth <timothy.vanreeth@kuleuven.be>
86+
"""
87+
88+
# Excluding nans from the input LCs to avoid problems
89+
ori_time0 = ori_lc.time[~np.isnan(ori_lc.flux)]
90+
ori_flux0 = ori_lc.flux[~np.isnan(ori_lc.flux)]
91+
corr_time0 = corrected_lc.time[~np.isnan(corrected_lc.flux)]
92+
corr_flux0 = corrected_lc.flux[~np.isnan(corrected_lc.flux)]
93+
94+
# Calculating the Noise floor of both LCs, defined as the differences between adjacent flux values
95+
ori_time = ori_time0[:-1]
96+
ori_Nf = ori_flux0[1:] - ori_flux0[:-1]
3397

34-
pass
98+
corr_time = corr_time0[:-1]
99+
corr_Nf = corr_flux0[1:] - corr_flux0[:-1]
100+
101+
# Computing the PSDs of the noise floors
102+
corr_fr,corr_psd = psd_scargle(corr_time, corr_Nf - np.mean(corr_Nf))
103+
ori_fr,ori_psd = psd_scargle(ori_time, ori_Nf - np.mean(ori_Nf))
104+
105+
# Ensuring both PSDs are evaluated for the same frequencies
106+
int_corr_psd = np.interp(ori_fr, corr_fr, corr_psd)
107+
108+
# Integrate the log of the ratio of PSDs, ensuring the integral exists
109+
if(np.r_[int_corr_psd < ori_psd].all()):
110+
Gn = -1.
111+
else:
112+
integrand = np.log10(int_corr_psd/ori_psd)
113+
integrand[np.r_[int_corr_psd < ori_psd]] = 0.
114+
Gn = alpha_n * np.trapz(integrand, x=ori_fr)
115+
116+
return Gn
117+
118+
35119

36-
# Check Kepler PDC Eq. 8.4-8.5
37120

38121

39122
class LCValidation(object):
@@ -185,6 +268,7 @@ def load_lightcurve(self, task, ver='RAW'):
185268

186269
return lc
187270

271+
188272
def search_database(self, select=None, search=None, order_by=None, limit=None, distinct=False):
189273
"""
190274
Search list of lightcurves and return a list of tasks/stars matching the given criteria.
@@ -352,6 +436,7 @@ def correlations(self, cbv_area):
352436
def added_noise(self):
353437

354438
#call wn on loaded targets
439+
355440
pass
356441

357442

@@ -453,4 +538,4 @@ def added_noise(self):
453538

454539

455540

456-
541+

corrections/taskmanager.py

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ def __init__(self, todo_file, cleanup=False, overwrite=False, summary=None, summ
4343
self.conn = sqlite3.connect(todo_file)
4444
self.conn.row_factory = sqlite3.Row
4545
self.cursor = self.conn.cursor()
46+
self.cursor.execute("PRAGMA foreign_keys=ON;")
4647

4748
self.summary_file = summary
4849
self.summary_interval = summary_interval
@@ -63,6 +64,10 @@ def __init__(self, todo_file, cleanup=False, overwrite=False, summary=None, summ
6364
self.cursor.execute("CREATE INDEX corr_status_idx ON todolist (corr_status);")
6465
self.conn.commit()
6566

67+
# Create indicies
68+
self.cursor.execute("CREATE INDEX IF NOT EXISTS datavalidation_raw_approved_idx ON datavalidation_raw (approved);")
69+
self.conn.commit()
70+
6671
# Reset the status of everything for a new run:
6772
if overwrite:
6873
self.cursor.execute("UPDATE todolist SET corr_status=NULL;")
@@ -73,7 +78,7 @@ def __init__(self, todo_file, cleanup=False, overwrite=False, summary=None, summ
7378
self.cursor.execute("""CREATE TABLE IF NOT EXISTS diagnostics_corr (
7479
priority INT PRIMARY KEY NOT NULL,
7580
lightcurve TEXT,
76-
elaptime REAL NOT NULL,
81+
elaptime REAL,
7782
worker_wait_time REAL NOT NULL,
7883
variance DOUBLE PRECISION,
7984
rms_hour DOUBLE PRECISION,
@@ -84,18 +89,22 @@ def __init__(self, todo_file, cleanup=False, overwrite=False, summary=None, summ
8489
self.conn.commit()
8590

8691
# Reset calculations with status STARTED or ABORT:
87-
clear_status = str(STATUS.STARTED.value) + ',' + str(STATUS.ABORT.value)
92+
clear_status = str(STATUS.STARTED.value) + ',' + str(STATUS.ABORT.value) + ',' + str(STATUS.ERROR.value)
8893
self.cursor.execute("DELETE FROM diagnostics_corr WHERE priority IN (SELECT todolist.priority FROM todolist WHERE corr_status IN (" + clear_status + "));")
8994
self.cursor.execute("UPDATE todolist SET corr_status=NULL WHERE corr_status IN (" + clear_status + ");")
9095
self.conn.commit()
91-
96+
97+
# Analyze the tables for better query planning:
98+
self.cursor.execute("ANALYZE;")
99+
92100
# Prepare summary object:
93101
self.summary = {
94102
'slurm_jobid': os.environ.get('SLURM_JOB_ID', None),
95103
'numtasks': 0,
96104
'tasks_run': 0,
97105
'last_error': None,
98-
'mean_elaptime': 0.0
106+
'mean_elaptime': None,
107+
'mean_worker_waittime': None
99108
}
100109
# Make sure to add all the different status to summary:
101110
for s in STATUS: self.summary[s.name] = 0
@@ -154,10 +163,9 @@ def get_number_tasks(self, starid=None, camera=None, ccd=None, datasource=None):
154163
else:
155164
constraints = ''
156165

157-
self.cursor.execute("SELECT COUNT(*) AS num FROM todolist INNER JOIN diagnostics ON todolist.priority=diagnostics.priority INNER JOIN datavalidation_raw ON todolist.priority=datavalidation_raw.priority WHERE status IN (%d,%d) AND (corr_status IS NULL OR corr_status = %d) AND datavalidation_raw.approved=1 %s ORDER BY todolist.priority LIMIT 1;" % (
166+
self.cursor.execute("SELECT COUNT(*) AS num FROM todolist INNER JOIN diagnostics ON todolist.priority=diagnostics.priority INNER JOIN datavalidation_raw ON todolist.priority=datavalidation_raw.priority WHERE status IN (%d,%d) AND corr_status IS NULL AND datavalidation_raw.approved=1 %s ORDER BY todolist.priority LIMIT 1;" % (
158167
STATUS.OK.value,
159168
STATUS.WARNING.value,
160-
STATUS.ERROR.value,
161169
constraints
162170
))
163171

@@ -188,11 +196,9 @@ def get_task(self, starid=None, camera=None, ccd=None, datasource=None):
188196
else:
189197
constraints = ''
190198

191-
192-
self.cursor.execute("SELECT * FROM todolist INNER JOIN diagnostics ON todolist.priority=diagnostics.priority INNER JOIN datavalidation_raw ON todolist.priority=datavalidation_raw.priority WHERE status IN (%d,%d) AND (corr_status IS NULL OR corr_status = %d) AND datavalidation_raw.approved=1 %s ORDER BY todolist.priority LIMIT 1;" % (
199+
self.cursor.execute("SELECT * FROM todolist INNER JOIN diagnostics ON todolist.priority=diagnostics.priority INNER JOIN datavalidation_raw ON todolist.priority=datavalidation_raw.priority WHERE status IN (%d,%d) AND corr_status IS NULL AND datavalidation_raw.approved=1 %s ORDER BY todolist.priority LIMIT 1;" % (
193200
STATUS.OK.value,
194201
STATUS.WARNING.value,
195-
STATUS.ERROR.value,
196202
constraints
197203
))
198204
task = self.cursor.fetchone()
@@ -203,7 +209,7 @@ def save_results(self, result):
203209

204210
# Extract details dictionary:
205211
details = result.get('details', {})
206-
212+
207213
# The status of this target returned by the photometry:
208214
my_status = result['status_corr']
209215

@@ -213,15 +219,14 @@ def save_results(self, result):
213219
result['status_corr'].value,
214220
result['priority']
215221
))
216-
222+
217223
self.summary['tasks_run'] += 1
218224
self.summary[my_status.name] += 1
219225
self.summary['STARTED'] -= 1
220-
226+
221227
# Save additional diagnostics:
222228
error_msg = details.get('errors', None)
223229
if error_msg:
224-
# error_msg = '\n'.join(error_msg)
225230
self.summary['last_error'] = error_msg
226231

227232
# Save additional diagnostics:
@@ -239,13 +244,22 @@ def save_results(self, result):
239244
except:
240245
self.conn.rollback()
241246
raise
242-
243-
# Calculate mean elapsed time using "streaming mean":
244-
self.summary['mean_elaptime'] += (result['elaptime_corr'] - self.summary['mean_elaptime']) / self.summary['tasks_run']
245-
247+
248+
# Calculate mean elapsed time using "streaming weighted mean" with (alpha=0.1):
249+
# https://dev.to/nestedsoftware/exponential-moving-average-on-streaming-data-4hhl
250+
if self.summary['mean_elaptime'] is None:
251+
self.summary['mean_elaptime'] = result['elaptime_corr']
252+
elif result.get('elaptime_corr') is not None:
253+
self.summary['mean_elaptime'] += 0.1 * (result['elaptime_corr'] - self.summary['mean_elaptime'])
254+
255+
if self.summary['mean_worker_waittime'] is None:
256+
self.summary['mean_worker_waittime'] = result['worker_wait_time']
257+
elif result.get('worker_wait_time') is not None:
258+
self.summary['mean_worker_waittime'] += 0.1 * (result['worker_wait_time'] - self.summary['mean_worker_waittime'])
259+
246260
# Write summary file:
247261
if self.summary_file and self.summary['tasks_run'] % self.summary_interval == 0:
248-
self.write_summary()
262+
self.write_summary()
249263

250264
def start_task(self, taskid):
251265
"""
@@ -254,8 +268,8 @@ def start_task(self, taskid):
254268
self.cursor.execute("UPDATE todolist SET corr_status=? WHERE priority=?;", (STATUS.STARTED.value, taskid))
255269
self.conn.commit()
256270
self.summary['STARTED'] += 1
257-
258-
271+
272+
259273
def get_random_task(self):
260274
"""
261275
Get random task to be processed.

corrections/version.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,9 @@ def get_version(pep440=False, include_branch=True):
151151
return read_release_version()
152152

153153
if include_branch:
154-
git_version = call_git_getbranch() + '-' + git_version
154+
git_branch = call_git_getbranch()
155+
if not git_branch is None:
156+
git_version = git_branch + '-' + git_version
155157

156158
return git_version
157159

0 commit comments

Comments
 (0)