Skip to content

Commit c422221

Browse files
committed
Merge branch 'devel'
2 parents dfac4eb + ff0179c commit c422221

File tree

7 files changed

+114
-30
lines changed

7 files changed

+114
-30
lines changed

.travis.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,12 @@ before_deploy:
7676
- cat VERSION
7777
deploy:
7878
provider: releases
79-
api_key: $GITHUB_TOKEN
80-
skip_cleanup: true
79+
token: $GITHUB_TOKEN
8180
draft: true
8281
name: "Version $TRAVIS_TAG"
83-
body: "Version $TRAVIS_TAG"
82+
release_notes: "Version $TRAVIS_TAG"
8483
on:
8584
branch:
8685
- master
87-
- /^v\d+\.\d+.+$/
86+
- /^v\d+\.\d+.*$/
8887
tags: true

VERSION

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

corrections/BaseCorrector.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,13 @@ def __init__(self, input_folder, plot=False):
8585
logging.getLogger('corrections').addHandler(handler)
8686

8787
# Save inputs:
88-
self.input_folder = input_folder
8988
self.plot = plot
89+
if os.path.isdir(input_folder):
90+
self.input_folder = input_folder
91+
todo_file = os.path.join(input_folder, 'todo.sqlite')
92+
else:
93+
self.input_folder = os.path.dirname(input_folder)
94+
todo_file = input_folder
9095

9196
self.CorrMethod = {
9297
'BaseCorrector': 'base',
@@ -110,7 +115,6 @@ def __init__(self, input_folder, plot=False):
110115
os.makedirs(self.data_folder, exist_ok=True)
111116

112117
# The path to the TODO list:
113-
todo_file = os.path.join(input_folder, 'todo.sqlite')
114118
logger.debug("TODO file: %s", todo_file)
115119
if not os.path.isfile(todo_file):
116120
raise FileNotFoundError("TODO file not found")
@@ -204,11 +208,11 @@ def correct(self, task, output_folder=None):
204208

205209
except (KeyboardInterrupt, SystemExit):
206210
status = STATUS.ABORT
207-
logger.warning("Correction was aborted.")
211+
logger.warning("Correction was aborted (priority=%d)", task['priority'])
208212

209213
except: # noqa: E722
210214
status = STATUS.ERROR
211-
logger.exception("Correction failed.")
215+
logger.exception("Correction failed (priority=%d)", task['priority'])
212216

213217
# Check that the status has been changed:
214218
if status == STATUS.UNKNOWN:

corrections/taskmanager.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212
import sqlite3
1313
import logging
1414
import json
15+
from numpy import atleast_1d
1516
from . import STATUS
1617

1718
class TaskManager(object):
1819
"""
1920
A TaskManager which keeps track of which targets to process.
2021
"""
2122

22-
def __init__(self, todo_file, cleanup=False, overwrite=False, summary=None, summary_interval=100):
23+
def __init__(self, todo_file, cleanup=False, overwrite=False, cleanup_constraints=None,
24+
summary=None, summary_interval=100):
2325
"""
2426
Initialize the TaskManager which keeps track of which targets to process.
2527
@@ -28,6 +30,12 @@ def __init__(self, todo_file, cleanup=False, overwrite=False, summary=None, summ
2830
cleanup (boolean, optional): Perform cleanup/optimization of TODO-file before
2931
during initialization. Default=False.
3032
overwrite (boolean, optional): Overwrite any previously calculated results. Default=False.
33+
cleanup_constraints (dict, optional): Dict of constraint for cleanup of the status of
34+
previous correction runs. If not specified, all bad results are cleaned up.
35+
summary (string, optional): Path to JSON file which will be periodically updated with
36+
a status summary of the corrections.
37+
summary_interval (integer, optional): Interval at which summary file is updated.
38+
Default=100.
3139
3240
Raises:
3341
FileNotFoundError: If TODO-file could not be found.
@@ -90,10 +98,21 @@ def __init__(self, todo_file, cleanup=False, overwrite=False, summary=None, summ
9098
);""")
9199
self.conn.commit()
92100

93-
# Reset calculations with status STARTED or ABORT:
101+
# Reset calculations with status STARTED, ABORT or ERROR:
94102
clear_status = str(STATUS.STARTED.value) + ',' + str(STATUS.ABORT.value) + ',' + str(STATUS.ERROR.value) + ',' + str(STATUS.SKIPPED.value)
95-
self.cursor.execute("DELETE FROM diagnostics_corr WHERE priority IN (SELECT todolist.priority FROM todolist WHERE corr_status IN (" + clear_status + "));")
96-
self.cursor.execute("UPDATE todolist SET corr_status=NULL WHERE corr_status IN (" + clear_status + ");")
103+
constraints = ['corr_status IN (' + clear_status + ')']
104+
105+
# Add additional constraints from the user input and build SQL query:
106+
if cleanup_constraints:
107+
cc = cleanup_constraints.copy()
108+
if cc.get('datasource'):
109+
constraints.append("datasource='ffi'" if cc.pop('datasource') == 'ffi' else "datasource!='ffi'")
110+
for key, val in cc.items():
111+
constraints.append(key + ' IN (%s)' % ','.join([str(v) for v in atleast_1d(val)]))
112+
113+
constraints = ' AND '.join(constraints)
114+
self.cursor.execute("DELETE FROM diagnostics_corr WHERE priority IN (SELECT todolist.priority FROM todolist WHERE " + constraints + ");")
115+
self.cursor.execute("UPDATE todolist SET corr_status=NULL WHERE " + constraints + ";")
97116
self.conn.commit()
98117

99118
# Set all targets that did not return good photometry or were not approved by the Data Validation to SKIPPED:
@@ -175,7 +194,7 @@ def get_number_tasks(self, starid=None, camera=None, ccd=None, datasource=None,
175194
if ccd is not None:
176195
constraints.append('todolist.ccd=%d' % ccd)
177196
if datasource is not None:
178-
constraints.append('todolist.datasource="%s"' % datasource)
197+
constraints.append("todolist.datasource='ffi'" if datasource == 'ffi' else "todolist.datasource!='ffi'")
179198

180199
if constraints:
181200
constraints = ' AND ' + " AND ".join(constraints)
@@ -208,7 +227,7 @@ def get_task(self, starid=None, camera=None, ccd=None, datasource=None, priority
208227
if ccd is not None:
209228
constraints.append('todolist.ccd=%d' % ccd)
210229
if datasource is not None:
211-
constraints.append('todolist.datasource="%s"' % datasource)
230+
constraints.append("todolist.datasource='ffi'" if datasource == 'ffi' else "todolist.datasource!='ffi'")
212231

213232
if constraints:
214233
constraints = ' AND ' + " AND ".join(constraints)

run_tesscorr.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,32 +72,35 @@ def main():
7272

7373
output_folder = args.output_folder
7474
if output_folder is None:
75-
output_folder = os.environ.get('TESSCORR_OUTPUT', os.path.join(input_folder, 'lightcurves'))
75+
output_folder = os.environ.get('TESSCORR_OUTPUT', os.path.join(os.path.dirname(input_folder), 'lightcurves'))
7676

7777
logger.info("Loading input data from '%s'", input_folder)
7878
logger.info("Putting output data in '%s'", output_folder)
7979

8080
# Make sure the output directory exists:
8181
os.makedirs(output_folder, exist_ok=True)
8282

83+
# Constraints on which targets to process:
84+
constraints = {
85+
'camera': args.camera,
86+
'ccd': args.ccd,
87+
'datasource': args.datasource,
88+
'starid': args.starid,
89+
'priority': args.priority
90+
}
91+
8392
# Get the class for the selected method:
8493
CorrClass = corrections.corrclass(args.method)
8594

8695
# Initialize the corrector class:
8796
with CorrClass(input_folder, plot=args.plot) as corr:
8897
# Start the TaskManager:
89-
with corrections.TaskManager(input_folder, overwrite=args.overwrite) as tm:
98+
with corrections.TaskManager(input_folder, overwrite=args.overwrite, cleanup_constraints=constraints) as tm:
9099
while True:
91100
if args.random:
92101
task = tm.get_random_task()
93102
else:
94-
task = tm.get_task(
95-
starid=args.starid,
96-
camera=args.camera,
97-
ccd=args.ccd,
98-
datasource=args.datasource,
99-
priority=args.priority
100-
)
103+
task = tm.get_task(**constraints)
101104

102105
if task is None: break
103106

run_tesscorr_mpi.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def main():
5959
input_folder = os.environ.get('TESSCORR_INPUT')
6060
if not input_folder:
6161
parser.error("Please specify an INPUT_FOLDER.")
62-
output_folder = os.environ.get('TESSCORR_OUTPUT', os.path.join(input_folder, 'lightcurves'))
62+
output_folder = os.environ.get('TESSCORR_OUTPUT', os.path.join(os.path.dirname(input_folder), 'lightcurves'))
6363

6464
# Define MPI message tags
6565
tags = enum.IntEnum('tags', ('READY', 'DONE', 'EXIT', 'START'))
@@ -72,12 +72,23 @@ def main():
7272

7373
if rank == 0:
7474
try:
75-
with corrections.TaskManager(input_folder, cleanup=True, overwrite=args.overwrite, summary=os.path.join(output_folder, 'summary_corr.json')) as tm:
75+
# Constraints on which targets to process:
76+
constraints = {
77+
'camera': args.camera,
78+
'ccd': args.ccd,
79+
'datasource': args.datasource
80+
}
81+
82+
# Start TaskManager, which keeps track of the task that needs to be performed:
83+
with corrections.TaskManager(input_folder, cleanup=True, overwrite=args.overwrite,
84+
cleanup_constraints=constraints,
85+
summary=os.path.join(output_folder, 'summary_corr.json')) as tm:
86+
7687
# Set level of TaskManager logger:
7788
tm.logger.setLevel(logging_level)
7889

7990
# Get list of tasks:
80-
numtasks = tm.get_number_tasks(camera=args.camera, ccd=args.ccd, datasource=args.datasource)
91+
numtasks = tm.get_number_tasks(**constraints)
8192
tm.logger.info("%d tasks to be run", numtasks)
8293

8394
# Start the master loop that will assign tasks
@@ -98,7 +109,7 @@ def main():
98109

99110
if tag in (tags.DONE, tags.READY):
100111
# Worker is ready, so send it a task
101-
task = tm.get_task(camera=args.camera, ccd=args.ccd, datasource=args.datasource)
112+
task = tm.get_task(**constraints)
102113
if task:
103114
task_index = task['priority']
104115
tm.start_task(task_index)
@@ -161,7 +172,7 @@ def main():
161172
error_msg = traceback.format_exc().strip()
162173
result.update({
163174
'status_corr': corrections.STATUS.ERROR,
164-
'details': {'errors': error_msg},
175+
'details': {'errors': [error_msg]},
165176
})
166177

167178
result.update({'worker_wait_time': toc-tic})

tests/test_taskmanager.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
1212
from corrections import TaskManager, STATUS
1313

14+
#--------------------------------------------------------------------------------------------------
1415
def test_taskmanager():
1516
"""Test of TaskManager"""
1617

17-
# Load the first image in the input directory:
1818
INPUT_DIR = os.path.join(os.path.dirname(__file__), 'input')
1919

2020
# Find the shape of the original image:
@@ -60,5 +60,53 @@ def test_taskmanager():
6060

6161
assert(task1_status == STATUS.STARTED.value)
6262

63+
#--------------------------------------------------------------------------------------------------
64+
def test_taskmanager_constraints():
65+
66+
INPUT_DIR = os.path.join(os.path.dirname(__file__), 'input')
67+
68+
constraints = {'datasource': 'tpf', 'priority': 17}
69+
with TaskManager(INPUT_DIR, overwrite=True, cleanup_constraints=constraints) as tm:
70+
task = tm.get_task(**constraints)
71+
print(task)
72+
assert task is None, "Task1 should be None"
73+
74+
constraints = {'datasource': 'ffi', 'priority': 17}
75+
with TaskManager(INPUT_DIR, overwrite=True, cleanup_constraints=constraints) as tm:
76+
task = tm.get_task(**constraints)
77+
print(task)
78+
assert task['priority'] == 17, "Task2 should be #17"
79+
80+
#--------------------------------------------------------------------------------------------------
81+
def test_taskmanager_cleanup():
82+
83+
INPUT_DIR = os.path.join(os.path.dirname(__file__), 'input')
84+
85+
# Reset the TODO-file completely, and mark the first task as STARTED:
86+
with TaskManager(INPUT_DIR, overwrite=True) as tm:
87+
task1 = tm.get_task()
88+
print(task1)
89+
pri = task1['priority']
90+
tm.start_task(pri)
91+
92+
# Cleanup, but with a constraint not matching the one we changed:
93+
with TaskManager(INPUT_DIR, cleanup_constraints={'priority': 18}) as tm:
94+
# Check that the status did actually change in the todolist:
95+
tm.cursor.execute("SELECT corr_status FROM todolist WHERE priority=?;", [pri])
96+
task1_status = tm.cursor.fetchone()['corr_status']
97+
print(task1_status)
98+
assert task1_status == STATUS.STARTED.value
99+
100+
# Now clean with a constraint that matches:
101+
with TaskManager(INPUT_DIR, cleanup_constraints={'priority': pri}) as tm:
102+
# Check that the status did actually change in the todolist:
103+
tm.cursor.execute("SELECT corr_status FROM todolist WHERE priority=?;", [pri])
104+
task1_status = tm.cursor.fetchone()['corr_status']
105+
print(task1_status)
106+
assert task1_status is None
107+
108+
#--------------------------------------------------------------------------------------------------
63109
if __name__ == '__main__':
64110
test_taskmanager()
111+
test_taskmanager_constraints()
112+
test_taskmanager_cleanup()

0 commit comments

Comments
 (0)