-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #39 from eteq/interactive
Interactive Notebook stuff
- Loading branch information
Showing
2 changed files
with
307 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"from __future__ import print_function\n", | ||
"\n", | ||
"import logging\n", | ||
"import webbrowser\n", | ||
"from cStringIO import StringIO\n", | ||
"\n", | ||
"import numpy as np\n", | ||
"\n", | ||
"from astropy.io import fits\n", | ||
"from stginga import nbinteract\n", | ||
"\n", | ||
"from IPython.html.widgets import interact\n", | ||
"from IPython import display" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"server = nbinteract.GingaServer()\n", | ||
"server.start()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"server.get_viewer_urls()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"display.IFrame(server.get_viewer_urls()['Main Viewer'], 625, 625)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"The next cell will open a new window with the same view as above" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"webbrowser.open(server.get_viewer_urls()['Main Viewer'])" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Note that this next cell may take some time to download the first time" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"f = fits.open('https://archive.stsci.edu/pub/hlsp/angst/acs/hlsp_angst_hst_acs-wfc_10210-ugc8760_f814w_v1_ref.fits')\n", | ||
"server.load_fits(f)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"You'll need to download have some acs image for this dataset to run the next cell. A convenient one (to match the above) might be: https://archive.stsci.edu/cgi-bin/mastpreview?mission=hst&dataid=J8YY05021" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"fi = fits.open('j8yy05kbq_drc.fits')\n", | ||
"\n", | ||
"@interact(hdunum=(1,3))\n", | ||
"def switch_hdu(hdunum=1):\n", | ||
" server.load_fits(fi[hdunum])" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"v = server.viewers['Main Viewer']\n", | ||
"aim = v.fitsimage.get_image()\n", | ||
"\n", | ||
"for r in v.canvas.get_objects()[1:]:\n", | ||
" corners = np.array(r.get_points())\n", | ||
" xmin, xmax = np.min(corners[:, 0]), np.max(corners[:, 0])\n", | ||
" ymin, ymax = np.min(corners[:, 1]), np.max(corners[:, 1])\n", | ||
" data_square = aim.get_data()[ymin:ymax, xmin:xmax]\n", | ||
" flux = np.sum(data_square)\n", | ||
" print('Rectangle centered on', r.get_center_pt(), 'has flux', flux)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"# clear all rectangles\n", | ||
"v = server.viewers['Main Viewer']\n", | ||
"v.canvas.deleteObjects(v.canvas.get_objects()[1:])" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Debug code " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"log = logging.Logger('nbinteract sio logger')\n", | ||
"logsio = StringIO()\n", | ||
"#log.addHandler(logging.StreamHandler(stream=logsio))\n", | ||
"log.addHandler(logging.NullHandler())" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 2", | ||
"language": "python", | ||
"name": "python2" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 2 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython2", | ||
"version": "2.7.10" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 0 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
"""Wrapper script to run Ginga optimized for STScI data.""" | ||
from __future__ import (absolute_import, division, print_function, | ||
unicode_literals) | ||
|
||
import os | ||
|
||
from astropy.io import fits | ||
from astropy.utils import isiterable | ||
|
||
import tornado.httpserver | ||
import tornado.web | ||
import tornado.ioloop | ||
|
||
from ginga.misc import log, Task | ||
from ginga.AstroImage import AstroImage | ||
from ginga.web.pgw import Widgets, js, PgHelp, ipg | ||
|
||
__all__ = ['start_server', 'GingaServer', ''] | ||
|
||
|
||
class GingaServer(object): | ||
def __init__(self, host='localhost', port=9909, logger=None, numthreads=5): | ||
self.tornado_app = None | ||
self.viewers = {} | ||
self.host = host | ||
self.port = port | ||
|
||
if logger is None: | ||
logger = log.get_logger("nbinteract_server", null=True) | ||
self.logger = logger | ||
|
||
self.thread_pool = Task.ThreadPool(numthreads, logger) | ||
self.app = Widgets.Application(logger=self.logger, base_url=self.base_url) | ||
|
||
@property | ||
def base_url(self): | ||
return "http://{0}:{1}/app".format(self.host, self.port) | ||
|
||
def __repr__(self): | ||
repr_str = object.__repr__(self) | ||
if self.url: | ||
urlstr = 'not started' | ||
else: | ||
urlstr = 'URL={0}'.format(self.url) | ||
return repr_str.replace('object at', urlstr + ' at') | ||
|
||
|
||
def start(self, create_main_window=True): | ||
self.thread_pool.startall() | ||
|
||
#TODO: DONT DO THIS. Use package data instead | ||
js_path = os.path.dirname(js.__file__) | ||
|
||
self.tornado_app = tornado.web.Application([ | ||
(r"/js/(.*\.js)", tornado.web.StaticFileHandler, | ||
{"path": js_path}), | ||
(r"/app", PgHelp.WindowHandler, | ||
dict(name='Application', url='/app', app=self.app)), | ||
(r"/app/socket", PgHelp.ApplicationHandler, | ||
dict(name='Ginga', app=self.app)), | ||
], logger=self.logger) | ||
|
||
|
||
self.tornado_server = tornado.httpserver.HTTPServer(self.tornado_app) | ||
self.tornado_server.listen(self.port, self.host) | ||
|
||
if create_main_window: | ||
self.new_viewer('Main Viewer') | ||
|
||
def stop(self): | ||
raise NotImplementedError | ||
|
||
def new_viewer(self, viewer_name,): | ||
""" | ||
Create a new viewer with the given name | ||
""" | ||
if viewer_name in self.viewers: | ||
raise ValueError('Viewer {} already exists'.format(viewer_name)) | ||
|
||
# our own viewer object, customized with methods (see above) | ||
self.viewers[viewer_name] = ipg.ImageViewer(self.logger, self.app.make_window(viewer_name)) | ||
return self.viewers[viewer_name] | ||
|
||
def get_viewer_urls(self): | ||
return {name: viewer.top.url for name, viewer in self.viewers.items()} | ||
|
||
|
||
def load_fits(self, fileorhdu, viewer_name='Main Viewer'): | ||
if isinstance(fileorhdu, file): | ||
fileorhdu = fits.HDUList.fromfile(fileorhdu) | ||
|
||
if isiterable(fileorhdu): | ||
for hdui in fileorhdu: | ||
if hasattr(hdui, 'is_image') and hdui.is_image: | ||
hdu = hdui | ||
break | ||
else: | ||
raise ValueError('fileorhdu was iterable but did not contain any image HDUs') | ||
elif hasattr(fileorhdu, 'data') and hasattr(fileorhdu,'header'): | ||
#quacks like an HDU - give it a shot | ||
hdu = fileorhdu | ||
else: | ||
raise ValueError('fileorhdu was not a fits file or HDU-ish thing') | ||
|
||
|
||
viewer = self.viewers[viewer_name] | ||
if viewer.fitsimage.get_image() is None: | ||
aim = AstroImage(logger=self.logger) | ||
aim.load_hdu(hdu) | ||
viewer.fitsimage.set_image(aim) | ||
else: | ||
viewer.fitsimage.get_image().load_hdu(hdu) |