#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# checkplotserver_handlers.py - Waqas Bhatti (wbhatti@astro.princeton.edu) -
# Jan 2017
'''
These are Tornado handlers for serving checkplots and operating on them.
'''
####################
## SYSTEM IMPORTS ##
####################
import os
import os.path
import logging
import numpy as np
from numpy import ndarray
######################################
## CUSTOM JSON ENCODER FOR FRONTEND ##
######################################
# we need this to send objects with the following types to the frontend:
# - bytes
# - ndarray
import json
[docs]class FrontendEncoder(json.JSONEncoder):
'''This overrides Python's default JSONEncoder so we can serialize custom
objects.
'''
[docs] def default(self, obj):
'''Overrides the default serializer for `JSONEncoder`.
This can serialize the following objects in addition to what
`JSONEncoder` can already do.
- `np.array`
- `bytes`
- `complex`
- `np.float64` and other `np.dtype` objects
Parameters
----------
obj : object
A Python object to serialize to JSON.
Returns
-------
str
A JSON encoded representation of the input object.
'''
if isinstance(obj, np.ndarray):
return obj.tolist()
elif isinstance(obj, bytes):
return obj.decode()
elif isinstance(obj, complex):
return (obj.real, obj.imag)
elif (isinstance(obj, (float, np.float64, np.float_)) and
not np.isfinite(obj)):
return None
elif isinstance(obj, (np.int8, np.int16, np.int32, np.int64)):
return int(obj)
else:
return json.JSONEncoder.default(self, obj)
# this replaces the default encoder and makes it so Tornado will do the right
# thing when it converts dicts to JSON when a
# tornado.web.RequestHandler.write(dict) is called.
json._default_encoder = FrontendEncoder()
#############
## LOGGING ##
#############
# get a logger
LOGGER = logging.getLogger(__name__)
#####################
## TORNADO IMPORTS ##
#####################
import tornado.ioloop
import tornado.httpserver
import tornado.web
###################
## LOCAL IMPORTS ##
###################
from ..varclass import varfeatures
from .. import lcfit
from ..varbase import signals
from ..checkplot.pkl_utils import _pkl_phased_magseries_plot
from ..periodbase import zgls
from ..periodbase import saov
from ..periodbase import smav
from ..periodbase import spdm
from ..periodbase import kbls
from ..periodbase import macf
############
## CONFIG ##
############
PFMETHODS = ['gls','pdm','acf','aov','mav','bls','win']
# this is the function map for arguments
CPTOOLMAP = {
# this is a special tool to remove all unsaved lctool results from the
# current checkplot pickle
'lctool-reset':{
'args':(),
'argtypes':(),
'kwargs':(),
'kwargtypes':(),
'kwargdefs':(),
'func':None,
'resloc':[],
},
# this is a special tool to get all unsaved lctool results from the
# current checkplot pickle
'lctool-results':{
'args':(),
'argtypes':(),
'kwargs':(),
'kwargtypes':(),
'kwargdefs':(),
'func':None,
'resloc':[],
},
## PERIOD SEARCH METHODS ##
'psearch-gls':{
'args':('times','mags','errs'),
'argtypes':(ndarray, ndarray, ndarray),
'kwargs':('startp','endp','magsarefluxes',
'autofreq','stepsize','nbestpeaks',
'sigclip[]', 'lctimefilters',
'lcmagfilters','periodepsilon'),
'kwargtypes':(float, float, bool,
bool, float, int,
list, str,
str, float),
'kwargdefs':(None, None, False,
True, 1.0e-4, 10,
None, None,
None, 0.1),
'func':zgls.pgen_lsp,
'resloc':['gls'],
},
'psearch-bls':{
'args':('times','mags','errs'),
'argtypes':(ndarray, ndarray, ndarray),
'kwargs':('startp','endp','magsarefluxes',
'autofreq','stepsize','nbestpeaks',
'sigclip[]','lctimefilters','lcmagfilters',
'periodepsilon','mintransitduration','maxtransitduration'),
'kwargtypes':(float, float, bool,
bool, float, int,
list, str, str,
float, float, float),
'kwargdefs':(0.1, 100.0, False,
True, 1.0e-4, 10,
None, None, None,
0.1, 0.01, 0.08),
'func':kbls.bls_parallel_pfind,
'resloc':['bls'],
},
'psearch-pdm':{
'args':('times','mags','errs'),
'argtypes':(ndarray, ndarray, ndarray),
'kwargs':('startp','endp','magsarefluxes',
'autofreq','stepsize','nbestpeaks',
'sigclip[]','lctimefilters','lcmagfilters',
'periodepsilon','phasebinsize','mindetperbin'),
'kwargtypes':(float, float, bool,
bool, float, int,
list, str, str,
float, float, int),
'kwargdefs':(None, None, False,
True, 1.0e-4, 10,
None, None, None,
0.1, 0.05, 9),
'func':spdm.stellingwerf_pdm,
'resloc':['pdm'],
},
'psearch-aov':{
'args':('times','mags','errs'),
'argtypes':(ndarray, ndarray, ndarray),
'kwargs':('startp','endp','magsarefluxes',
'autofreq','stepsize','nbestpeaks',
'sigclip[]','lctimefilters','lcmagfilters',
'periodepsilon','phasebinsize','mindetperbin'),
'kwargtypes':(float, float, bool,
bool, float, int,
list, str, str,
float, float, int),
'kwargdefs':(None, None, False,
True, 1.0e-4, 10,
None, None, None,
0.1, 0.05, 9),
'func':saov.aov_periodfind,
'resloc':['aov'],
},
'psearch-mav':{
'args':('times','mags','errs'),
'argtypes':(ndarray, ndarray, ndarray),
'kwargs':('startp','endp','magsarefluxes',
'autofreq','stepsize','nbestpeaks',
'sigclip[]','lctimefilters','lcmagfilters',
'periodepsilon','nharmonics'),
'kwargtypes':(float, float, bool,
bool, float, int,
list, str, str,
float, int),
'kwargdefs':(None, None, False,
True, 1.0e-4, 10,
None, None, None,
0.1, 6),
'func':smav.aovhm_periodfind,
'resloc':['mav'],
},
'psearch-acf':{
'args':('times','mags','errs'),
'argtypes':(ndarray, ndarray, ndarray),
'kwargs':('startp','endp','magsarefluxes',
'autofreq','stepsize','smoothacf',
'sigclip[]','lctimefilters', 'lcmagfilters',
'periodepsilon', 'fillgaps'),
'kwargtypes':(float, float, bool,
bool, float, int,
list, str, str,
float, float),
'kwargdefs':(None, None, False,
True, 1.0e-4, 721,
None, None, None,
0.1, 0.0),
'func':macf.macf_period_find,
'resloc':['acf'],
},
'psearch-win':{
'args':('times','mags','errs'),
'argtypes':(ndarray, ndarray, ndarray),
'kwargs':('startp','endp','magsarefluxes',
'autofreq','stepsize','nbestpeaks',
'sigclip[]','lctimefilters','lcmagfilters',
'periodepsilon'),
'kwargtypes':(float, float, bool,
bool, float, int,
list, str, str,
float),
'kwargdefs':(None, None, False,
True, 1.0e-4, 10,
None, None, None,
0.1),
'func':zgls.specwindow_lsp,
'resloc':['win'],
},
## PLOTTING A NEW PHASED LC ##
'phasedlc-newplot':{
'args':(None,'lspmethod','periodind',
'times','mags','errs','varperiod','varepoch'),
'argtypes':(None, str, int, ndarray, ndarray, ndarray, float, float),
'kwargs':('xliminsetmode','magsarefluxes',
'phasewrap','phasesort',
'phasebin','plotxlim[]',
'sigclip[]','lctimefilters','lcmagfilters'),
'kwargtypes':(bool, bool, bool, bool, float, list, list, str, str),
'kwargdefs':(False, False, True, True, 0.002, [-0.8,0.8],
None, None, None),
'func':_pkl_phased_magseries_plot,
'resloc':[],
},
# FIXME: add sigclip, lctimefilters, and lcmagfilters for all of these
## VARIABILITY TOOLS ##
'var-varfeatures':{
'args':('times','mags','errs'),
'argtypes':(ndarray,ndarray,ndarray),
'kwargs':(),
'kwargtypes':(),
'kwargdefs':(),
'func':varfeatures.all_nonperiodic_features,
'resloc':['varinfo','features'],
},
'var-prewhiten':{
'args':('times','mags','errs','whitenperiod', 'whitenparams[]'),
'argtypes':(ndarray, ndarray, ndarray, float, list),
'kwargs':('magsarefluxes',),
'kwargtypes':(bool,),
'kwargdefs':(False,),
'func':signals.prewhiten_magseries,
'resloc':['signals','prewhiten'],
},
'var-masksig':{
'args':('times','mags','errs','signalperiod','signalepoch'),
'argtypes':(ndarray, ndarray, ndarray, float, float),
'kwargs':('magsarefluxes','maskphases[]','maskphaselength'),
'kwargtypes':(bool, list, float),
'kwargdefs':(False, [0.0,0.5,1.0], 0.1),
'func':signals.mask_signal,
'resloc':['signals','mask'],
},
# FIXME: add sigclip, lctimefilters, and lcmagfilters for all of these
## FITTING FUNCTIONS TO LIGHT CURVES ##
# this is a special call to just subtract an already fit function from the
# current light curve
'lcfit-subtract':{
'args':('fitmethod', 'periodind'),
'argtypes':(str, int),
'kwargs':(),
'kwargtypes':(),
'kwargdefs':(),
'func':None,
'resloc':[],
},
'lcfit-fourier':{
'args':('times','mags','errs','period'),
'argtypes':(ndarray, ndarray, ndarray, float),
'kwargs':('fourierorder','magsarefluxes', 'fourierparams[]'),
'kwargtypes':(int, bool, list),
'kwargdefs':(6, False, []),
'func':lcfit.fourier_fit_magseries,
'resloc':['fitinfo','fourier'],
},
'lcfit-spline':{
'args':('times','mags','errs','period'),
'argtypes':(ndarray, ndarray, ndarray, float),
'kwargs':('maxknots','knotfraction','magsarefluxes'),
'kwargtypes':(int, float, bool),
'kwargdefs':(30, 0.01, False),
'func':lcfit.spline_fit_magseries,
'resloc':['fitinfo','spline'],
},
'lcfit-legendre':{
'args':('times','mags','errs','period'),
'argtypes':(ndarray, ndarray, ndarray, float),
'kwargs':('legendredeg','magsarefluxes'),
'kwargtypes':(int, bool),
'kwargdefs':(10, False),
'func':lcfit.legendre_fit_magseries,
'resloc':['fitinfo','legendre'],
},
'lcfit-savgol':{
'args':('times','mags','errs','period'),
'argtypes':(ndarray, ndarray, ndarray, float),
'kwargs':('windowlength','magsarefluxes'),
'kwargtypes':(int, bool),
'kwargdefs':(None, False),
'func':lcfit.savgol_fit_magseries,
'resloc':['fitinfo','savgol'],
},
}
#####################
## HANDLER CLASSES ##
#####################
[docs]class IndexHandler(tornado.web.RequestHandler):
'''This handles the index page.
This page shows the current project.
'''
[docs] def initialize(self, currentdir, assetpath, cplist,
cplistfile, executor, readonly, baseurl):
'''
handles initial setup.
'''
self.currentdir = currentdir
self.assetpath = assetpath
self.currentproject = cplist
self.cplistfile = cplistfile
self.executor = executor
self.readonly = readonly
self.baseurl = baseurl
[docs] def get(self):
'''This handles GET requests to the index page.
TODO: provide the correct baseurl from the checkplotserver options dict,
so the frontend JS can just read that off immediately.
'''
# generate the project's list of checkplots
project_checkplots = self.currentproject['checkplots']
project_checkplotbasenames = [os.path.basename(x)
for x in project_checkplots]
project_checkplotindices = range(len(project_checkplots))
# get the sortkey and order
project_cpsortkey = self.currentproject['sortkey']
if self.currentproject['sortorder'] == 'asc':
project_cpsortorder = 'ascending'
elif self.currentproject['sortorder'] == 'desc':
project_cpsortorder = 'descending'
# get the filterkey and condition
project_cpfilterstatements = self.currentproject['filterstatements']
self.render('cpindex.html',
project_checkplots=project_checkplots,
project_cpsortorder=project_cpsortorder,
project_cpsortkey=project_cpsortkey,
project_cpfilterstatements=project_cpfilterstatements,
project_checkplotbasenames=project_checkplotbasenames,
project_checkplotindices=project_checkplotindices,
project_checkplotfile=self.cplistfile,
readonly=self.readonly,
baseurl=self.baseurl)