From 647c6550ad3979a1cc15e9e48dc220dfa8941f53 Mon Sep 17 00:00:00 2001 From: Eric Jeschke Date: Thu, 30 Mar 2017 17:28:04 -1000 Subject: [PATCH] Updates to use new help feature - updated some other plugins to use the new help feature - bumped release - updated example notebook for remote reference viewer control --- ..._control_of_a_Ginga_reference_viewer.ipynb | 474 +++++++++--------- ginga/rv/Control.py | 65 +-- ginga/rv/plugins/Blink.py | 4 +- ginga/rv/plugins/Crosshair.py | 4 +- ginga/rv/plugins/Cuts.py | 2 +- ginga/rv/plugins/Histogram.py | 4 +- ginga/rv/plugins/Overlays.py | 4 +- ginga/rv/plugins/PixTable.py | 4 +- ginga/rv/plugins/Ruler.py | 6 +- setup.cfg | 2 +- 10 files changed, 307 insertions(+), 262 deletions(-) diff --git a/ginga/examples/jupyter-notebook/Remote_control_of_a_Ginga_reference_viewer.ipynb b/ginga/examples/jupyter-notebook/Remote_control_of_a_Ginga_reference_viewer.ipynb index 7e92f1b61..2483940e5 100644 --- a/ginga/examples/jupyter-notebook/Remote_control_of_a_Ginga_reference_viewer.ipynb +++ b/ginga/examples/jupyter-notebook/Remote_control_of_a_Ginga_reference_viewer.ipynb @@ -1,239 +1,265 @@ { - "metadata": { - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ + "cells": [ { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "from ginga import __version__\n", - "__version__" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 118, - "text": [ - "'2.5.20160408100758'" - ] - } - ], - "prompt_number": 118 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# import ginga remote control module\n", - "from ginga.util import grc" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Start up the reference viewer *and invoke the \"RC\" (Remote Control) plugin from the \"Plugins\" menu*" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# for debugging\n", - "reload(grc)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 119, - "text": [ - "" - ] - } - ], - "prompt_number": 119 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# host and port parameters can be set in the graphical ui of the plugin.\n", - "# These are the defaults\n", - "viewer = grc.RemoteClient('localhost', 9000)" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 120 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# This gives you a handle to the reference viewer shell.\n", - "# It is similar to what you can do from the command line with:\n", - "# $ grc ginga ...\n", - "#\n", - "shell = viewer.shell()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 121 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# If you get a lot of errors when you run this, it might be because you didn't start\n", - "# the RC plugin in the viewer\n", - "shell.add_channel('Messier')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 123, - "text": [ - "'#UNDEFINED'" - ] - } - ], - "prompt_number": 123 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# This gives you a handle to a reference viewer channel.\n", - "# It is similar to what you can do from the command line with:\n", - "# $ grc channel ...\n", - "#\n", - "ch = viewer.channel('Messier')" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 124 - }, + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "from ginga import __version__\n", + "__version__" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "# import ginga remote control module\n", + "from ginga.util import grc" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "Start up the reference viewer *and invoke the \"RC\" (Remote Control) plugin from the \"Plugins\" menu*" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "# host and port parameters can be set in the graphical ui of the plugin.\n", + "# These are the defaults\n", + "viewer = grc.RemoteClient('localhost', 9000)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "# This gives you a handle to the reference viewer shell.\n", + "# It is similar to what you can do from the command line with:\n", + "# $ grc ginga ...\n", + "#\n", + "shell = viewer.shell()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "# example of loading an HDU from an astropy HDUlist\n", - "# parameters are (image_name, channel_name, hdulist, hdulist_key)\n", - "#\n", - "from astropy.io import fits\n", - "hdulist = fits.open(\"/home/eric/testdata/SPCAM/SUPA01118766.fits\", \"readonly\")\n", - "ch.load_hdu(\"M27\", hdulist, 0)" - ], - "language": "python", + "data": { + "text/plain": [ + "'#UNDEFINED'" + ] + }, + "execution_count": 12, "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 125, - "text": [ - "0" - ] - } - ], - "prompt_number": 125 - }, + "output_type": "execute_result" + } + ], + "source": [ + "# If you get a lot of errors when you run this, it might be because you didn't start\n", + "# the RC plugin in the viewer\n", + "shell.add_channel('Messier')" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "# This gives you a handle to a reference viewer channel.\n", + "# It is similar to what you can do from the command line with:\n", + "# $ grc channel ...\n", + "#\n", + "ch = viewer.channel('Messier')" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "# example\n", - "shell.zoom_in()" - ], - "language": "python", + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 14, "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 126, - "text": [ - "True" - ] - } - ], - "prompt_number": 126 - }, + "output_type": "execute_result" + } + ], + "source": [ + "# example of loading an HDU from an astropy HDUlist\n", + "# parameters are (image_name, channel_name, hdulist, hdulist_key)\n", + "#\n", + "from astropy.io import fits\n", + "hdulist = fits.open(\"camera.fits\", \"readonly\")\n", + "ch.load_hdu(\"M27\", hdulist, 0)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "ch.set_color_map('rainbow3')" - ], - "language": "python", + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 15, "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 127, - "text": [ - "'#UNDEFINED'" - ] - } - ], - "prompt_number": 127 - }, + "output_type": "execute_result" + } + ], + "source": [ + "# example\n", + "shell.zoom_in()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "# example of loading numpy arrays directly\n", - "# parameters are (image_name, channel_name, array, image_type, header_dict)\n", - "#\n", - "import numpy as np\n", - "data_np = np.random.randint(0, 2000, (512, 512))\n", - "ch.load_np(\"image\", data_np, 'fits', {})" - ], - "language": "python", + "data": { + "text/plain": [ + "'#UNDEFINED'" + ] + }, + "execution_count": 16, "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 128, - "text": [ - "0" - ] - } - ], - "prompt_number": 128 - }, + "output_type": "execute_result" + } + ], + "source": [ + "ch.set_color_map('rainbow3')" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [], - "language": "python", + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 17, "metadata": {}, - "outputs": [] + "output_type": "execute_result" } ], - "metadata": {} + "source": [ + "# example of loading numpy arrays directly\n", + "# parameters are (image_name, channel_name, array, image_type, header_dict)\n", + "#\n", + "import numpy as np\n", + "data_np = np.random.randint(0, 2000, (512, 512))\n", + "ch.load_np(\"image\", data_np, 'fits', {})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] } - ] -} \ No newline at end of file + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/ginga/rv/Control.py b/ginga/rv/Control.py index f66883ac4..bd764b2c4 100644 --- a/ginga/rv/Control.py +++ b/ginga/rv/Control.py @@ -335,17 +335,20 @@ def error_wrap(self, method, *args, **kwargs): self.logger.error(errmsg) self.gui_do(self.show_error, errmsg, raisetab=True) - def help(self, text=None, text_kind='url', trim_pfx=0): + def help_text(self, name, text, text_kind='plain', trim_pfx=0): """ Provide help text for the user. Parameters ---------- - text : str or None (optional) - The text to show. Should be a URL, HTML text or RST text + name : str + Category of help to show. + + text : str + The text to show. Should be plain, HTML or RST text text_kind : str (optional) - One of 'url', 'html', 'rst'. Default is 'url'. + One of 'plain', 'html', 'rst'. Default is 'plain'. trim_pfx : int (optional) Number of spaces to trim off the beginning of each line of text. @@ -356,34 +359,38 @@ def help(self, text=None, text_kind='url', trim_pfx=0): displayed in a plain text widget. """ - if text is not None: - if trim_pfx > 0: - # caller wants to trim some space off the front - # of each line - text = toolbox.trim_prefix(text, trim_pfx) + if trim_pfx > 0: + # caller wants to trim some space off the front + # of each line + text = toolbox.trim_prefix(text, trim_pfx) - if text_kind in ('html', 'url'): - pass + if text_kind == 'rst': + # try to convert RST to HTML using docutils + try: + overrides = {'input_encoding': 'ascii', + 'output_encoding': 'utf-8'} + text_html = publish_string(text, writer_name='html', + settings_overrides=overrides) + # docutils produces 'bytes' output, but webkit needs + # a utf-8 string + text = text_html.decode('utf-8') + text_kind = 'html' - elif text_kind == 'rst': - # try to convert RST to HTML using docutils - try: - overrides = {'input_encoding': 'ascii', - 'output_encoding': 'utf-8'} - text_html = publish_string(text, writer_name='html', - settings_overrides=overrides) - # docutils produces 'bytes' output, but webkit needs - # a utf-8 string - text = text_html.decode('utf-8') - - except Exception as e: - self.logger.error("Error converting help text to HTML: %s" % ( - str(e))) - # revert to showing RST as plain text - return self.show_help_text('Help', text) + except Exception as e: + self.logger.error("Error converting help text to HTML: %s" % ( + str(e))) + # revert to showing RST as plain text - else: - raise ValueError("I don't know how to display text of kind '%s'" % (text_kind)) + else: + raise ValueError("I don't know how to display text of kind '%s'" % (text_kind)) + + if text_kind == 'html': + self.help(text=text, text_kind='html') + + else: + self.show_help_text(name, text) + + def help(self, text=None, text_kind='url'): if not self.gpmon.has_plugin('WBrowser'): return self.show_error("help() requires 'WBrowser' plugin") diff --git a/ginga/rv/plugins/Blink.py b/ginga/rv/plugins/Blink.py index 57b9cf2b0..47dffd604 100644 --- a/ginga/rv/plugins/Blink.py +++ b/ginga/rv/plugins/Blink.py @@ -11,6 +11,8 @@ class Blink(GingaPlugin.LocalPlugin): """ + Blink + ===== Blink switches through the images shown in a channel at a rate chosen by the user. Alternatively, it can switch between channels in the main workspace. In both cases, the primary purpose is to @@ -130,7 +132,7 @@ def build_gui(self, container): def help(self): name = str(self).capitalize() - self.fv.show_help_text(name, self.__doc__) + self.fv.help_text(name, self.__doc__, text_kind='rst', trim_pfx=4) def close(self): if self.fitsimage is None: diff --git a/ginga/rv/plugins/Crosshair.py b/ginga/rv/plugins/Crosshair.py index 5f2e51d68..067682d1b 100644 --- a/ginga/rv/plugins/Crosshair.py +++ b/ginga/rv/plugins/Crosshair.py @@ -9,6 +9,8 @@ class Crosshair(GingaPlugin.LocalPlugin): """ + Crosshair + ========= Crosshair is a simple plugin to draw crosshairs labeled with the position of the cross in pixels coordinates, WCS coordinates or data value at the cross position. @@ -107,7 +109,7 @@ def set_format(self): def help(self): name = str(self).capitalize() - self.fv.show_help_text(name, self.__doc__) + self.fv.help_text(name, self.__doc__, text_kind='rst', trim_pfx=4) def close(self): self.fv.stop_local_plugin(self.chname, str(self)) diff --git a/ginga/rv/plugins/Cuts.py b/ginga/rv/plugins/Cuts.py index b047eeee3..43c3aa4d8 100644 --- a/ginga/rv/plugins/Cuts.py +++ b/ginga/rv/plugins/Cuts.py @@ -364,7 +364,7 @@ def axes_callback_handler(self, chkbox, pos): def help(self): name = str(self).capitalize() - self.fv.help(text=self.__doc__, text_kind='rst', trim_pfx=4) + self.fv.help_text(name, self.__doc__, text_kind='rst', trim_pfx=4) def select_cut(self, tag): self.cutstag = tag diff --git a/ginga/rv/plugins/Histogram.py b/ginga/rv/plugins/Histogram.py index c6d0944cc..fca55232c 100644 --- a/ginga/rv/plugins/Histogram.py +++ b/ginga/rv/plugins/Histogram.py @@ -14,6 +14,8 @@ class Histogram(GingaPlugin.LocalPlugin): """ + Histogram + ========= Histogram plots a histogram for a region drawn in the image, or for the entire image. @@ -212,7 +214,7 @@ def close(self): def help(self): name = str(self).capitalize() - self.fv.show_help_text(name, self.__doc__) + self.fv.help_text(name, self.__doc__, text_kind='rst', trim_pfx=4) def start(self): self.plot.set_titles(rtitle="Histogram") diff --git a/ginga/rv/plugins/Overlays.py b/ginga/rv/plugins/Overlays.py index 0c6993c02..c93481b73 100644 --- a/ginga/rv/plugins/Overlays.py +++ b/ginga/rv/plugins/Overlays.py @@ -11,6 +11,8 @@ class Overlays(GingaPlugin.LocalPlugin): """ + Overlays + ======== A plugin for generating color overlays representing under- and overexposure in the loaded image. @@ -133,7 +135,7 @@ def build_gui(self, container): def help(self): name = str(self).capitalize() - self.fv.show_help_text(name, self.__doc__) + self.fv.help_text(name, self.__doc__, text_kind='rst', trim_pfx=4) def close(self): self.fv.stop_local_plugin(self.chname, str(self)) diff --git a/ginga/rv/plugins/PixTable.py b/ginga/rv/plugins/PixTable.py index 4b750b49b..52cb33554 100644 --- a/ginga/rv/plugins/PixTable.py +++ b/ginga/rv/plugins/PixTable.py @@ -12,6 +12,8 @@ class PixTable(GingaPlugin.LocalPlugin): """ + PixTable + ======== PixTable provides a way to check or monitor the pixel values in a region. @@ -320,7 +322,7 @@ def close(self): def help(self): name = str(self).capitalize() - self.fv.show_help_text(name, self.__doc__) + self.fv.help_text(name, self.__doc__, text_kind='rst', trim_pfx=4) def start(self): # insert layer if it is not already diff --git a/ginga/rv/plugins/Ruler.py b/ginga/rv/plugins/Ruler.py index 5c6770ad8..c31a88ac6 100644 --- a/ginga/rv/plugins/Ruler.py +++ b/ginga/rv/plugins/Ruler.py @@ -9,6 +9,8 @@ class Ruler(GingaPlugin.LocalPlugin): """ + Ruler + ===== Ruler is a simple plugin designed to measure distances on an image. It does this by calculating a spherical triangulation via WCS mapping of three points defined by a single line drawn on the image. By default, @@ -16,7 +18,7 @@ class Ruler(GingaPlugin.LocalPlugin): it can be changed to show degrees or pixel distance instead. [ Should you want "sticky rulers", use the Drawing plugin (and choose - "Ruler" as the drawing type). ] + "Ruler" as the drawing type). ] Usage ----- @@ -148,7 +150,7 @@ def close(self): def help(self): name = str(self).capitalize() - self.fv.show_help_text(name, self.__doc__) + self.fv.help_text(name, self.__doc__, text_kind='rst', trim_pfx=4) def start(self): # start ruler drawing operation diff --git a/setup.cfg b/setup.cfg index b6d05a493..1d628a2e1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,7 +26,7 @@ license = BSD url = http://ejeschke.github.com/ginga edit_on_github = False github_project = ejeschke/ginga/ -version = 2.6.3.dev +version = 2.6.3 keywords = scientific image viewer numpy toolkit astronomy FITS classifiers = Intended Audience :: Science/Research,