Example #1
0
    def __init__(self):
        assert isinstance(self, CanvasMixin), "Missing CanvasMixin class"

        from .CanvasObject import drawCatalog
        # For interactive drawing
        self.candraw = False
        self.draw_dict = drawCatalog
        # canvas objects which we know how to draw have an "idraw"
        # class method
        self.drawtypes = [ key for key in self.draw_dict.keys()
                           if hasattr(self.draw_dict[key], 'idraw') ]
        self.drawtypes.sort()
        self.t_drawtype = 'point'
        self.t_drawparams = {}
        # holds the drawing context
        self._draw_cxt = None

        # For interactive editing
        self.canedit = False
        # Set to False to disable drag moves except from move control pt
        self.easymove = True
        self._start_x = 0
        self._start_y = 0
        self._cp_index = None
        self._edit_obj = None
        self._edit_status = False

        # For modes
        self._mode = 'draw'
        self._mode_tbl = Bunch()
        self.add_draw_mode(None)
        self.add_draw_mode('draw', down=self.draw_start,
                           move=self.draw_motion, up=self.draw_stop,
                           poly_add=self.draw_poly_add,
                           poly_delete=self.draw_poly_delete)
        self.add_draw_mode('edit', down=self.edit_start,
                           move=self.edit_motion, up=self.edit_stop,
                           poly_add=self.edit_poly_add,
                           poly_delete=self.edit_poly_delete)

        # For selection
        self._selected = []
        self.multi_select_ok = False

        # this controls whether an object is automatically selected for
        # editing immediately after being drawn
        self.edit_follows_draw = False

        self._process_time = 0.0
        # time delta threshold for deciding whether to update the image
        self._delta_time = 0.020
        self._draw_obj = None

        # NOTE: must be mixed in with a Callback.Callbacks
        for name in ('draw-event', 'draw-down', 'draw-move', 'draw-up',
                     'cursor-down', 'cursor-up', 'cursor-move',
                     'draw-scroll', 'keydown-poly_add', 'keydown-poly_del',
                     'keydown-edit_del', 'edit-event',
                     'edit-select', 'drag-drop'):
            self.enable_callback(name)
Example #2
0
 def add_global_plugin(self,
                       module_name,
                       ws_name,
                       path=None,
                       klass=None,
                       category='Global',
                       tab_name=None,
                       start_plugin=True,
                       pfx=None):
     self.add_plugin_spec(
         Bunch(module=module_name,
               workspace=ws_name,
               tab=tab_name,
               path=path,
               klass=klass,
               category=category,
               ptype='global',
               start=start_plugin,
               pfx=pfx))
Example #3
0
    def createTab(self):
        # If we have already created (and possibly closed) this
        # proposal tab before, just reload it. Otherwise, we have to
        # create it from scratch.
        proposal = self.model.proposalForPropTab
        self.logger.info('Creating tab for proposal %s' % proposal)
        if self.view.gpmon.has_plugin(proposal):
            self.view.reload_plugin(proposal)
        else:
            spec = Bunch(module='ProposalTab',
                         klass='ProposalTab',
                         ws='report',
                         tab=proposal,
                         name=proposal,
                         start=False,
                         ptype='global')
            self.view.load_plugin(proposal, spec)

        self.view.start_plugin(proposal)

        # Raise the tab we just created
        self.view.ds.raise_tab(proposal)
Example #4
0
    def draw_start(self, canvas, event, data_x, data_y, viewer):
        if not self.candraw:
            return False

        self._draw_obj = None
        self.clear_selected()

        # get the drawing coordinate type (default 'data')
        crdtype = self.t_drawparams.get('coord', 'data')
        crdmap = viewer.get_coordmap(crdtype)
        x, y = crdmap.data_to(data_x, data_y)

        klass = self.draw_dict.get(self.t_drawtype, None)

        # create the drawing context
        self._draw_cxt = Bunch(start_x=x, start_y=y, points=[(x, y)],
                               x=x, y=y, data_x=data_x, data_y=data_y,
                               drawparams=self.t_drawparams,
                               crdmap=crdmap, viewer=viewer,
                               draw_class=klass, logger=self.logger)

        self._draw_update(data_x, data_y, self._draw_cxt, force_update=True)
        return True
Example #5
0
def _get_stginga_plugins():
    # TODO: When we use stable Ginga release, not the dev, we can remove this
    # and just have version check in setup.py
    if ginga_version < '2.5.20160222004742':
        warnings.warn('Your Ginga version {0} is old, stginga might not work '
                      'properly'.format(ginga_version), AstropyUserWarning)

    gpfx = 'stginga.plugins'  # To load custom plugins in Ginga namespace

    global_plugins = []
    local_plugins = [
        Bunch(module='MultiImage', ws='dialogs', pfx=gpfx),
        Bunch(module='MIPick', ws='dialogs', pfx=gpfx),
        Bunch(module='BackgroundSub', ws='dialogs', pfx=gpfx),
        Bunch(module='BadPixCorr', ws='dialogs', pfx=gpfx),
        Bunch(module='DQInspect', ws='dialogs', pfx=gpfx),
        Bunch(module='SNRCalc', ws='dialogs', pfx=gpfx),
        ]
    return global_plugins, local_plugins
def setup_CSU_initializer():
    spec = Bunch(path=os.path.join(p_path, 'CSU_initializer.py'),
                 module='CSU_initializer', klass='CSU_initializer',
                 ptype='local', workspace='dialogs',
                 category="Keck", menu="CSU_initializer", tab='CSU_initializer')
    return spec
Example #7
0
    def __init__(self):
        assert isinstance(self, CanvasMixin), "Missing CanvasMixin class"

        from .CanvasObject import drawCatalog
        # For interactive drawing
        self.candraw = False
        self.draw_dict = drawCatalog
        # canvas objects which we know how to draw have an "idraw"
        # class method
        self.drawtypes = [ key for key in self.draw_dict.keys()
                           if hasattr(self.draw_dict[key], 'idraw') ]
        self.drawtypes.sort()
        self.t_drawtype = 'point'
        self.t_drawparams = {}
        # holds the drawing context
        self._draw_cxt = None

        # For interactive editing
        self.canedit = False
        # Set to False to disable drag moves except from move control pt
        self.easymove = True
        self._start_x = 0
        self._start_y = 0
        self._cp_index = None
        self._edit_obj = None
        self._edit_status = False
        self._edit_detail = {}
        self._pick_cur_obj = None

        # For modes
        self._mode = 'draw'
        self._mode_tbl = Bunch()
        self.add_draw_mode(None)
        self.add_draw_mode('draw', down=self.draw_start,
                           move=self.draw_motion, up=self.draw_stop,
                           poly_add=self.draw_poly_add,
                           poly_delete=self.draw_poly_delete)
        self.add_draw_mode('edit', down=self.edit_start,
                           move=self.edit_motion, up=self.edit_stop,
                           poly_add=self.edit_poly_add,
                           poly_delete=self.edit_poly_delete)
        self.add_draw_mode('pick', down=self.pick_start,
                           move=self.pick_motion, up=self.pick_stop,
                           hover=self.pick_hover,
                           poly_add=self.edit_poly_add,
                           poly_delete=self.edit_poly_delete)

        # For selection
        self._selected = []
        self.multi_select_ok = False

        # this controls whether an object is automatically selected for
        # editing immediately after being drawn
        self.edit_follows_draw = False

        self._process_time = 0.0
        # time delta threshold for deciding whether to update the image
        self._delta_time = 0.020
        self._draw_obj = None

        # NOTE: must be mixed in with a Callback.Callbacks
        for name in ('draw-event', 'draw-down', 'draw-move', 'draw-up',
                     'cursor-down', 'cursor-up', 'cursor-move',
                     'draw-scroll', 'keydown-poly_add', 'keydown-poly_del',
                     'keydown-edit_del', 'edit-event',
                     'edit-select', 'drag-drop', 'cursor-changed'):
            self.enable_callback(name)
Example #8
0
            stretch=1),
        dict(row=[
            'ws',
            dict(name='toolbar', wstype='stack', height=40, group=2)
        ],
             stretch=0),
        dict(row=['hbox', dict(name='status')], stretch=0),
    ]
]

plugins = [
    # hidden plugins, started at program initialization
    Bunch(module='Operations',
          workspace='operations',
          start=True,
          hidden=True,
          category='System',
          menu="Operations [G]",
          ptype='global'),
    Bunch(module='Toolbar',
          workspace='toolbar',
          start=True,
          hidden=True,
          category='System',
          menu="Toolbar [G]",
          ptype='global'),
    Bunch(module='Pan',
          workspace='uleft',
          start=True,
          hidden=True,
          category='System',
Example #9
0
def setup_cometaryenhancements():
    spec = Bunch(path=os.path.join(p_path, 'CometaryEnhancements.py'),
                 module='CometaryEnhancements',
                 klass='CometaryEnhancements',
                 workspace='dialogs')
    return spec
Example #10
0
                      ['ws',
                       dict(name='dialogs', wstype='tabs', group=2)])]
                ],
            ],
            stretch=1),
        dict(row=[
            'ws',
            dict(name='toolbar', wstype='stack', height=40, group=2)
        ],
             stretch=0),
        dict(row=['hbox', dict(name='status')], stretch=0),
    ]
]

global_plugins = [
    Bunch(module='Toolbar', tab='Toolbar', ws='toolbar'),
    Bunch(module='Pan', tab='_pan', ws='uleft', raisekey=None),
    Bunch(module='Info', tab='Synopsis', ws='lleft', raisekey=None),
    Bunch(module='Header', tab='Header', ws='left', raisekey='H'),
    Bunch(module='Zoom', tab='Zoom', ws='left', raisekey='Z'),
    Bunch(module='Thumbs', tab='Thumbs', ws='right', raisekey='T'),
    Bunch(module='Contents', tab='Contents', ws='right', raisekey='c'),
    Bunch(module='Colorbar', tab='_cbar', ws='cbar', start=True),
    Bunch(module='Cursor', tab='_readout', ws='readout', start=True),
    Bunch(module='Operations', tab='_opns', ws='operations', start=True),
    Bunch(module='WBrowser',
          tab='Help',
          ws='channels',
          raisekey='?',
          start=False),
    Bunch(module='FBrowser', tab='Open File', ws='right', start=False),
Example #11
0
    def main(self, options, args):
        """
        Main routine for running the reference viewer.

        `options` is a OptionParser object that has been populated with
        values from parsing the command line.  It should at least include
        the options from add_default_options()

        `args` is a list of arguments to the viewer after parsing out
        options.  It should contain a list of files or URLs to load.
        """

        # Create a logger
        logger = log.get_logger(name='ginga', options=options)

        # Get settings (preferences)
        basedir = paths.ginga_home
        if not os.path.exists(basedir):
            try:
                os.mkdir(basedir)
            except OSError as e:
                logger.warn("Couldn't create ginga settings area (%s): %s" %
                            (basedir, str(e)))
                logger.warn("Preferences will not be able to be saved")

        # Set up preferences
        prefs = Settings.Preferences(basefolder=basedir, logger=logger)
        settings = prefs.createCategory('general')
        settings.load(onError='silent')
        settings.setDefaults(useMatplotlibColormaps=False,
                             widgetSet='choose',
                             WCSpkg='choose',
                             FITSpkg='choose',
                             recursion_limit=2000)

        # default of 1000 is a little too small
        sys.setrecursionlimit(settings.get('recursion_limit'))

        # So we can find our plugins
        sys.path.insert(0, basedir)
        moduleHome = os.path.split(sys.modules['ginga.version'].__file__)[0]
        childDir = os.path.join(moduleHome, 'misc', 'plugins')
        sys.path.insert(0, childDir)
        pluginDir = os.path.join(basedir, 'plugins')
        sys.path.insert(0, pluginDir)

        # Choose a toolkit
        if options.toolkit:
            toolkit = options.toolkit
        else:
            toolkit = settings.get('widgetSet', 'choose')

        if toolkit == 'choose':
            try:
                from ginga.qtw import QtHelp
            except ImportError:
                try:
                    from ginga.gtkw import GtkHelp
                except ImportError:
                    print("You need python-gtk or python-qt to run Ginga!")
                    sys.exit(1)
        else:
            ginga_toolkit.use(toolkit)

        tkname = ginga_toolkit.get_family()
        logger.info("Chosen toolkit (%s) family is '%s'" %
                    (ginga_toolkit.toolkit, tkname))

        # these imports have to be here, otherwise they force the choice
        # of toolkit too early
        from ginga.gw.GingaGw import GingaView
        from ginga.Control import GingaControl, GuiLogHandler

        # Define class dynamically based on toolkit choice
        class GingaShell(GingaControl, GingaView):
            def __init__(self,
                         logger,
                         thread_pool,
                         module_manager,
                         prefs,
                         ev_quit=None):
                GingaView.__init__(self, logger, ev_quit, thread_pool)
                GingaControl.__init__(self,
                                      logger,
                                      thread_pool,
                                      module_manager,
                                      prefs,
                                      ev_quit=ev_quit)

        if settings.get('useMatplotlibColormaps', False):
            # Add matplotlib color maps if matplotlib is installed
            try:
                from ginga import cmap
                cmap.add_matplotlib_cmaps()
            except Exception as e:
                logger.warn("failed to load matplotlib colormaps: %s" %
                            (str(e)))

        # User wants to customize the WCS package?
        if options.wcspkg:
            wcspkg = options.wcspkg
        else:
            wcspkg = settings.get('WCSpkg', 'choose')

        try:
            from ginga.util import wcsmod
            assert wcsmod.use(wcspkg) == True
        except Exception as e:
            logger.warn("failed to set WCS package preference: %s" % (str(e)))

        # User wants to customize the FITS package?
        if options.fitspkg:
            fitspkg = options.fitspkg
        else:
            fitspkg = settings.get('FITSpkg', 'choose')

        try:
            from ginga.util import io_fits
            assert io_fits.use(fitspkg) == True
        except Exception as e:
            logger.warn("failed to set FITS package preference: %s" % (str(e)))

        # Check whether user wants to use OpenCv
        use_opencv = settings.get('use_opencv', False)
        if use_opencv or options.opencv:
            from ginga import trcalc
            try:
                trcalc.use('opencv')
            except Exception as e:
                logger.warn("failed to set OpenCv preference: %s" % (str(e)))

        # Create the dynamic module manager
        mm = ModuleManager.ModuleManager(logger)

        # Create and start thread pool
        ev_quit = threading.Event()
        thread_pool = Task.ThreadPool(options.numthreads,
                                      logger,
                                      ev_quit=ev_quit)
        thread_pool.startall()

        # Create the Ginga main object
        ginga_shell = GingaShell(logger,
                                 thread_pool,
                                 mm,
                                 prefs,
                                 ev_quit=ev_quit)
        ginga_shell.set_layout(self.layout)

        gc = os.path.join(basedir, "ginga_config.py")
        have_ginga_config = os.path.exists(gc)

        # User configuration (custom star catalogs, etc.)
        if have_ginga_config:
            try:
                import ginga_config

                ginga_config.pre_gui_config(ginga_shell)
            except Exception as e:
                try:
                    (type, value, tb) = sys.exc_info()
                    tb_str = "\n".join(traceback.format_tb(tb))

                except Exception:
                    tb_str = "Traceback information unavailable."

                logger.error("Error importing Ginga config file: %s" %
                             (str(e)))
                logger.error("Traceback:\n%s" % (tb_str))

        # Build desired layout
        ginga_shell.build_toplevel()

        # Did user specify a particular geometry?
        if options.geometry:
            ginga_shell.set_geometry(options.geometry)

        # make the list of disabled plugins
        disabled_plugins = []
        if not (options.disable_plugins is None):
            disabled_plugins = options.disable_plugins.lower().split(',')

        # Add desired global plugins
        for spec in self.global_plugins:
            if not spec.module.lower() in disabled_plugins:
                ginga_shell.add_global_plugin(spec)

        # Add GUI log handler (for "Log" global plugin)
        guiHdlr = GuiLogHandler(ginga_shell)
        guiHdlr.setLevel(options.loglevel)
        fmt = logging.Formatter(log.LOG_FORMAT)
        guiHdlr.setFormatter(fmt)
        logger.addHandler(guiHdlr)

        # Load any custom modules
        if options.modules:
            modules = options.modules.split(',')
            for longPluginName in modules:
                if '.' in longPluginName:
                    tmpstr = longPluginName.split('.')
                    pluginName = tmpstr[-1]
                    pfx = '.'.join(tmpstr[:-1])
                else:
                    pluginName = longPluginName
                    pfx = None
                spec = Bunch(name=pluginName,
                             module=pluginName,
                             tab=pluginName,
                             ws='right',
                             pfx=pfx)
                ginga_shell.add_global_plugin(spec)

        # Load modules for "local" (per-channel) plug ins
        for spec in self.local_plugins:
            if not spec.module.lower() in disabled_plugins:
                ginga_shell.add_local_plugin(spec)

        # Load any custom plugins
        if options.plugins:
            plugins = options.plugins.split(',')
            for longPluginName in plugins:
                if '.' in longPluginName:
                    tmpstr = longPluginName.split('.')
                    pluginName = tmpstr[-1]
                    pfx = '.'.join(tmpstr[:-1])
                else:
                    pluginName = longPluginName
                    pfx = None
                spec = Bunch(module=pluginName,
                             ws='dialogs',
                             hidden=False,
                             pfx=pfx)
                ginga_shell.add_local_plugin(spec)

        ginga_shell.update_pending()

        # TEMP?
        tab_names = list(
            map(lambda name: name.lower(),
                ginga_shell.ds.get_tabnames(group=None)))
        if 'info' in tab_names:
            ginga_shell.ds.raise_tab('Info')
        if 'thumbs' in tab_names:
            ginga_shell.ds.raise_tab('Thumbs')

        # Add custom channels
        channels = options.channels.split(',')
        for chname in channels:
            ginga_shell.add_channel(chname)
        ginga_shell.change_channel(channels[0])

        # User configuration (custom star catalogs, etc.)
        if have_ginga_config:
            try:
                ginga_config.post_gui_config(ginga_shell)
            except Exception as e:
                try:
                    (type, value, tb) = sys.exc_info()
                    tb_str = "\n".join(traceback.format_tb(tb))

                except Exception:
                    tb_str = "Traceback information unavailable."

                logger.error("Error processing Ginga config file: %s" %
                             (str(e)))
                logger.error("Traceback:\n%s" % (tb_str))

        # Redirect warnings to logger
        for hdlr in logger.handlers:
            logging.getLogger('py.warnings').addHandler(hdlr)

        # Display banner the first time run, unless suppressed
        showBanner = True
        try:
            showBanner = settings.get('showBanner')

        except KeyError:
            # disable for subsequent runs
            settings.set(showBanner=False)
            settings.save()

        if (not options.nosplash) and (len(args) == 0) and showBanner:
            ginga_shell.banner(raiseTab=True)

        # Assume remaining arguments are fits files and load them.
        for imgfile in args:
            ginga_shell.nongui_do(ginga_shell.load_file, imgfile)

        try:
            try:
                # if there is a network component, start it
                if hasattr(ginga_shell, 'start'):
                    task = Task.FuncTask2(ginga_shell.start)
                    thread_pool.addTask(task)

                # Main loop to handle GUI events
                logger.info("Entering mainloop...")
                ginga_shell.mainloop(timeout=0.001)

            except KeyboardInterrupt:
                logger.error("Received keyboard interrupt!")

        finally:
            logger.info("Shutting down...")
            ev_quit.set()

        sys.exit(0)
Example #12
0
    qexec.py --help
    qexec.py [options]
"""
import sys, os

from ginga.misc.Bunch import Bunch

from qplan import main, version

defaultServiceName = 'qexecute'

plugins = [
    Bunch(name='slewchart',
          module='SlewChart',
          klass='SlewChart',
          ptype='global',
          tab='Slew Chart',
          ws='sub2',
          start=True),
    Bunch(name='airmasschart',
          module='AirMassChart',
          klass='AirMassChart',
          ptype='global',
          tab='Airmass Chart',
          ws='sub1',
          start=True),
    Bunch(name='schedule',
          module='Schedule',
          klass='Schedule',
          ptype='global',
          tab='Schedule',
Example #13
0
def main(options, args):

    # default of 1000 is a little too small
    sys.setrecursionlimit(2000)

    # Create a logger
    logger = log.get_logger(name='ginga', options=options)

    # Get settings (preferences)
    basedir = paths.ginga_home
    if not os.path.exists(basedir):
        try:
            os.mkdir(basedir)
        except OSError as e:
            logger.warn("Couldn't create ginga settings area (%s): %s" %
                        (basedir, str(e)))
            logger.warn("Preferences will not be able to be saved")

    # Set up preferences
    prefs = Settings.Preferences(basefolder=basedir, logger=logger)
    settings = prefs.createCategory('general')
    settings.load(onError='silent')
    settings.setDefaults(useMatplotlibColormaps=False,
                         widgetSet='choose',
                         WCSpkg='choose',
                         FITSpkg='choose')

    # So we can find our plugins
    sys.path.insert(0, basedir)
    moduleHome = os.path.split(sys.modules['ginga.version'].__file__)[0]
    childDir = os.path.join(moduleHome, 'misc', 'plugins')
    sys.path.insert(0, childDir)
    pluginDir = os.path.join(basedir, 'plugins')
    sys.path.insert(0, pluginDir)

    # Choose a toolkit
    if options.toolkit:
        toolkit = options.toolkit
    else:
        toolkit = settings.get('widgetSet', 'choose')

    ginga_toolkit.use(toolkit)
    tkname = ginga_toolkit.get_family()

    if tkname == 'gtk':
        from ginga.gtkw.GingaGtk import GingaView
    elif tkname == 'qt':
        from ginga.qtw.GingaQt import GingaView
    else:
        try:
            from ginga.qtw.GingaQt import GingaView
        except ImportError:
            try:
                from ginga.gtkw.GingaGtk import GingaView
            except ImportError:
                print("You need python-gtk or python-qt4 to run Ginga!")
                sys.exit(1)

    # Define class dynamically based on toolkit choice
    class Ginga(GingaControl, GingaView):
        def __init__(self,
                     logger,
                     threadPool,
                     module_manager,
                     prefs,
                     ev_quit=None):
            GingaView.__init__(self, logger, ev_quit)
            GingaControl.__init__(self,
                                  logger,
                                  threadPool,
                                  module_manager,
                                  prefs,
                                  ev_quit=ev_quit)

    if settings.get('useMatplotlibColormaps', False):
        # Add matplotlib color maps if matplotlib is installed
        try:
            from ginga import cmap
            cmap.add_matplotlib_cmaps()
        except Exception as e:
            logger.warn("failed to load matplotlib colormaps: %s" % (str(e)))

    # User wants to customize the WCS package?
    if options.wcs:
        wcspkg = options.wcs
    else:
        wcspkg = settings.get('WCSpkg', 'choose')

    try:
        from ginga.util import wcsmod
        assert wcsmod.use(wcspkg) == True
    except Exception as e:
        logger.warn("failed to set WCS package preference: %s" % (str(e)))

    # User wants to customize the FITS package?
    if options.fits:
        fitspkg = options.fits
    else:
        fitspkg = settings.get('FITSpkg', 'choose')

    try:
        from ginga.util import io_fits
        assert io_fits.use(fitspkg) == True
    except Exception as e:
        logger.warn("failed to set FITS package preference: %s" % (str(e)))

    # Create the dynamic module manager
    mm = ModuleManager.ModuleManager(logger)

    # Create and start thread pool
    ev_quit = threading.Event()
    threadPool = Task.ThreadPool(options.numthreads, logger, ev_quit=ev_quit)
    threadPool.startall()

    # Create the Ginga main object
    ginga = Ginga(logger, threadPool, mm, prefs, ev_quit=ev_quit)
    ginga.set_layout(default_layout)

    # User configuration (custom star catalogs, etc.)
    try:
        import ginga_config

        ginga_config.pre_gui_config(ginga)
    except Exception as e:
        try:
            (type, value, tb) = sys.exc_info()
            tb_str = "\n".join(traceback.format_tb(tb))

        except Exception:
            tb_str = "Traceback information unavailable."

        logger.error("Error importing Ginga config file: %s" % (str(e)))
        logger.error("Traceback:\n%s" % (tb_str))

    # Build desired layout
    ginga.build_toplevel()

    # Did user specify a particular geometry?
    if options.geometry:
        ginga.setGeometry(options.geometry)

    # Add desired global plugins
    for spec in global_plugins:
        ginga.add_global_plugin(spec)

    # Add GUI log handler (for "Log" global plugin)
    guiHdlr = GuiLogHandler(ginga)
    guiHdlr.setLevel(options.loglevel)
    fmt = logging.Formatter(log.LOG_FORMAT)
    guiHdlr.setFormatter(fmt)
    logger.addHandler(guiHdlr)

    # Load any custom modules
    if options.modules:
        modules = options.modules.split(',')
        for pluginName in modules:
            spec = Bunch(name=pluginName,
                         module=pluginName,
                         tab=pluginName,
                         ws='right')
            ginga.add_global_plugin(spec)

    # Load modules for "local" (per-channel) plug ins
    for spec in local_plugins:
        ginga.add_local_plugin(spec)

    # Load any custom plugins
    if options.plugins:
        plugins = options.plugins.split(',')
        for pluginName in plugins:
            spec = Bunch(module=pluginName, ws='dialogs', hidden=False)
            ginga.add_local_plugin(spec)

    ginga.update_pending()

    # TEMP?
    ginga.ds.raise_tab('Info')
    ginga.ds.raise_tab('Thumbs')

    # Add custom channels
    channels = options.channels.split(',')
    for chname in channels:
        datasrc = Datasrc.Datasrc(length=options.bufsize)
        ginga.add_channel(chname, datasrc)
    ginga.change_channel(channels[0])

    # User configuration (custom star catalogs, etc.)
    try:
        ginga_config.post_gui_config(ginga)
    except Exception as e:
        try:
            (type, value, tb) = sys.exc_info()
            tb_str = "\n".join(traceback.format_tb(tb))

        except Exception:
            tb_str = "Traceback information unavailable."

        logger.error("Error processing Ginga config file: %s" % (str(e)))
        logger.error("Traceback:\n%s" % (tb_str))

    # Display banner the first time run, unless suppressed
    showBanner = True
    try:
        showBanner = settings.get('showBanner')

    except KeyError:
        # disable for subsequent runs
        settings.set(showBanner=False)
        settings.save()

    if (not options.nosplash) and (len(args) == 0) and showBanner:
        ginga.banner()

    # Assume remaining arguments are fits files and load them.
    for imgfile in args:
        ginga.nongui_do(ginga.load_file, imgfile)

    try:
        try:
            # Main loop to handle GUI events
            logger.info("Entering mainloop...")
            ginga.mainloop(timeout=0.001)

        except KeyboardInterrupt:
            logger.error("Received keyboard interrupt!")

    finally:
        logger.info("Shutting down...")
        ev_quit.set()

    sys.exit(0)
Example #14
0
    def edit_start(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit:
            return False

        self._edit_tmp = self._edit_obj
        self._edit_status = False
        self._edit_detail = Bunch()
        self._cp_index = None
        #shift_held = 'shift' in event.modifiers
        shift_held = False

        selects = self.get_selected()
        if len(selects) == 0:
            #print("no objects already selected")
            # <-- no objects already selected

            # check for objects at this location
            #print("getting items")
            objs = canvas.select_items_at(viewer, data_x, data_y,
                                          test=self._is_editable)
            #print("items: %s" % (str(objs)))

            if len(objs) == 0:
                # <-- no objects under cursor
                return False

            # pick top object
            obj = objs[-1]
            self._prepare_to_move(obj, data_x, data_y)

        else:
            self._edit_status = True

            # Ugh.  Check each selected object's control points
            # for a match
            contains = []
            for obj in selects:
                #print("editing: checking for cp")
                edit_pts = obj.get_edit_points(viewer)
                #print((self._edit_obj, edit_pts))
                i = obj.get_pt(viewer, edit_pts, data_x, data_y,
                               obj.cap_radius)
                #print(('got point', i))
                if i is not None:
                    #print("editing cp #%d" % (i))
                    # editing a control point from an existing object
                    self._edit_obj = obj
                    self._cp_index = i
                    if hasattr(obj, 'rot_deg'):
                        x, y = self._rot_xlate(self._edit_obj, data_x, data_y)
                    else:
                        x, y = data_x, data_y
                    self._edit_detail.start_pos = (x, y)
                    obj.setup_edit(self._edit_detail)
                    self._edit_update(data_x, data_y, viewer)
                    return True

                ## if obj.contains(data_x, data_y):
                ##     contains.append(obj)
                # update: check if objects bbox contains this point
                x1, y1, x2, y2 = obj.get_llur()
                if (x1 <= data_x <= x2) and (y1 <= data_y <= y2):
                    contains.append(obj)

            # <-- no control points match, is there an object that contains
            # this point?
            if len(contains) > 0:
                # TODO?: make a compound object of contains and move it?
                obj = contains[-1]
                if self.is_selected(obj) and shift_held:
                    # deselecting object
                    self.select_remove(obj)
                else:
                    self._prepare_to_move(obj, data_x, data_y)
                    ## Compound = self.get_draw_class('compoundobject')
                    ## c_obj = Compound(*self.get_selected())
                    ## c_obj.inherit_from(obj)
                    ## self._prepare_to_move(c_obj, data_x, data_y)

            else:
                # <-- user clicked outside any selected item's control pt
                # and outside any selected item
                if not shift_held:
                    self.clear_selected()

                # see now if there is an unselected item at this location
                objs = canvas.select_items_at(viewer, data_x, data_y,
                                              test=self._is_editable)
                #print("new items: %s" % (str(objs)))
                if len(objs) > 0:
                    # pick top object
                    obj = objs[-1]
                    #print(("top object", obj))
                    if self.num_selected() > 0:
                        #print("there are previously selected items")
                        # if there are already some selected items, then
                        # add this object to the selection, make a compound
                        # object
                        self.edit_select(obj)
                        Compound = self.get_draw_class('compoundobject')
                        c_obj = Compound(*self.get_selected())
                        c_obj.inherit_from(obj)
                        self._prepare_to_move(c_obj, data_x, data_y)
                    else:
                        # otherwise just start over with this new object
                        #print(("starting over"))
                        self._prepare_to_move(obj, data_x, data_y)

        self.process_drawing()
        return True
Example #15
0
    def update_scheduler(self, use_db=False, ignore_pgm_skip_flag=False):
        sdlr = self.model.get_scheduler()
        try:
            sdlr.set_weights(self.weights_qf.weights)
            sdlr.set_schedule_info(self.schedule_qf.schedule_info)
            pgms = self.programs_qf.programs_info
            sdlr.set_programs_info(pgms, ignore_pgm_skip_flag)
            self.logger.info('list of programs to be scheduled %s' %
                             sdlr.programs.keys())

            # TODO: this maybe should be done in the Model
            ob_keys = set([])
            propnames = list(self.programs_qf.programs_info.keys())
            okprops = []
            ob_dict = {}
            # Note: if the ignore_pgm_skip_flag is set to True, then
            # we don't pay attention to the "skip" flag in the
            # Programs sheet and thus consider all OB's in all
            # Programs. Otherwise, we do pay attention to the "skip"
            # flag and ignore all OB's in "skipped" programs.
            for propname in propnames:
                if not ignore_pgm_skip_flag and pgms[propname].skip:
                    self.logger.info(
                        'skip flag for program %s is set - skipping all OB in this program'
                        % propname)
                    continue
                okprops.append(propname)

                # get all OB keys for this program
                for ob in self.ob_qf_dict[propname].obs_info:
                    key = (propname, ob.name)
                    ob_keys.add(key)
                    ob_dict[key] = ob

            self.logger.info("%s OBs after excluding skipped programs." %
                             (len(ob_keys)))

            # Remove keys for OBs that are already executed
            if use_db:
                self.connect_qdb()

                do_not_execute = set(self.qq.get_do_not_execute_ob_keys())

                # Painful reconstruction of time already accumulated
                # running the programs for executed OBS.  Inform scheduler
                # so that it can correcly calculate when to stop
                # allocating OBs for a program that has reached its
                # time limit.
                props = {}
                for ob_key in do_not_execute:
                    (propid, obcode) = ob_key[:2]
                    ob = self.qq.get_ob(ob_key)
                    bnch = props.setdefault(propid,
                                            Bunch(obcount=0, sched_time=0.0))
                    bnch.sched_time += ob.acct_time
                    bnch.obcount += 1

                sdlr.set_apriori_program_info(props)

                ob_keys -= do_not_execute

            elif self.model.completed_obs is not None:
                do_not_execute = set(self.model.completed_obs.keys())

                # See comment above.
                props = {}
                for ob_key in do_not_execute:
                    (propid, obcode) = ob_key[:2]
                    bnch = props.setdefault(propid,
                                            Bunch(obcount=0, sched_time=0.0))
                    info = self.model.completed_obs[ob_key]
                    bnch.sched_time += info['acct_time']
                    bnch.obcount += 1

                sdlr.set_apriori_program_info(props)

                ob_keys -= do_not_execute

            self.logger.info("%s OBs after removing executed OBs." %
                             (len(ob_keys)))

            # for a deterministic result
            ob_keys = list(ob_keys)
            ob_keys.sort()

            # Now turn the keys back into actual OB list
            oblist_info = []
            for key in ob_keys:
                oblist_info.append(ob_dict[key])

            self.oblist_info = oblist_info

            # TODO: only needed if we ADD or REMOVE programs
            sdlr.set_oblist_info(self.oblist_info)

        except Exception as e:
            self.logger.error("Error storing into scheduler: %s" % (str(e)))

        self.logger.info("scheduler initialized")
Example #16
0
def setup_MultiBars():
    spec = Bunch(path=os.path.join(p_path, 'MultiBars.py'),
                 module='MultiBars',
                 klass='MultiBars',
                 workspace='dialogs')
    return spec
Example #17
0
def setup_CSU_initializer():
    spec = Bunch(path=os.path.join(p_path, 'CSU_initializer.py'),
                 module='CSU_initializer',
                 klass='CSU_initializer',
                 workspace='dialogs')
    return spec
Example #18
0
def setup_mylocalplugin():
    spec = Bunch(path=os.path.join(p_path, 'MyLocalPlugin.py'),
                 module='MyLocalPlugin',
                 klass='MyLocalPlugin',
                 workspace='dialogs')
    return spec
Example #19
0
class DrawingMixin(object):
    """The DrawingMixin is a mixin class that adds drawing capability for
    some of the basic CanvasObject-derived types.  The set_surface method is
    used to associate a ImageViewCanvas object for layering on.
    """

    def __init__(self):
        assert isinstance(self, CanvasMixin), "Missing CanvasMixin class"

        from .CanvasObject import drawCatalog
        # For interactive drawing
        self.candraw = False
        self.draw_dict = drawCatalog
        # canvas objects which we know how to draw have an "idraw"
        # class method
        self.drawtypes = [ key for key in self.draw_dict.keys()
                           if hasattr(self.draw_dict[key], 'idraw') ]
        self.drawtypes.sort()
        self.t_drawtype = 'point'
        self.t_drawparams = {}
        # holds the drawing context
        self._draw_cxt = None

        # For interactive editing
        self.canedit = False
        # Set to False to disable drag moves except from move control pt
        self.easymove = True
        self._start_x = 0
        self._start_y = 0
        self._cp_index = None
        self._edit_obj = None
        self._edit_status = False

        # For modes
        self._mode = 'draw'
        self._mode_tbl = Bunch()
        self.add_draw_mode(None)
        self.add_draw_mode('draw', down=self.draw_start,
                           move=self.draw_motion, up=self.draw_stop,
                           poly_add=self.draw_poly_add,
                           poly_delete=self.draw_poly_delete)
        self.add_draw_mode('edit', down=self.edit_start,
                           move=self.edit_motion, up=self.edit_stop,
                           poly_add=self.edit_poly_add,
                           poly_delete=self.edit_poly_delete)

        # For selection
        self._selected = []
        self.multi_select_ok = False

        # this controls whether an object is automatically selected for
        # editing immediately after being drawn
        self.edit_follows_draw = False

        self._process_time = 0.0
        # time delta threshold for deciding whether to update the image
        self._delta_time = 0.020
        self._draw_obj = None

        # NOTE: must be mixed in with a Callback.Callbacks
        for name in ('draw-event', 'draw-down', 'draw-move', 'draw-up',
                     'cursor-down', 'cursor-up', 'cursor-move',
                     'draw-scroll', 'keydown-poly_add', 'keydown-poly_del',
                     'keydown-edit_del', 'edit-event',
                     'edit-select', 'drag-drop'):
            self.enable_callback(name)

    def set_surface(self, viewer):
        self.viewer = viewer

        # register this canvas for events of interest
        canvas = self

        # for legacy drawing via draw mode in Bindmap
        canvas.add_callback('draw-down', self.draw_start, viewer)
        canvas.add_callback('draw-move', self.draw_motion, viewer)
        canvas.add_callback('draw-up', self.draw_stop, viewer)

        canvas.add_callback('key-press', self._draw_key, 'key', viewer)
        canvas.add_callback('keydown-poly_add', self._draw_op, 'poly_add',
                          viewer)
        canvas.add_callback('keydown-poly_del', self._draw_op, 'poly_delete',
                          viewer)
        canvas.add_callback('keydown-edit_del', self.edit_delete_cb, viewer)
        #canvas.add_callback('draw-scroll', self._edit_rotate_cb, viewer)
        #canvas.add_callback('draw-scroll', self._edit_scale_cb, viewer)

    def get_surface(self):
        return self.viewer

    def register_for_cursor_drawing(self, viewer):
        canvas = self
        canvas.add_callback('cursor-down', self._draw_op, 'down', viewer)
        canvas.add_callback('cursor-move', self._draw_op, 'move', viewer)
        canvas.add_callback('cursor-up', self._draw_op, 'up', viewer)

    ##### MODE LOGIC #####

    def add_draw_mode(self, name, **kwargs):
        try:
            bnch = self._mode_tbl[name]
        except KeyError:
            bnch = Bunch(name=name, **kwargs)
            self._mode_tbl[name] = bnch

        return bnch

    def set_draw_mode(self, mode):
        if not mode in self._mode_tbl:
            modes = list(self._mode_tbl.keys())
            raise ValueError("mode must be one of: %s" % (str(modes)))

        self._mode = mode
        if mode != 'edit':
            self.clear_selected()

        self.update_canvas()

    def get_draw_mode(self):
        return self._mode

    def _draw_op(self, canvas, event, data_x, data_y, opn, viewer):
        if viewer != event.viewer:
            return False

        mode = self._mode
        # Hack to handle legacy drawing using draw mode in Bindmap
        if self.is_drawing():
            mode = 'draw'

        try:
            method = self._mode_tbl[mode][opn]
        except KeyError:
            return False

        if method is not None:
            return method(canvas, event, data_x, data_y, viewer)
        return False

    def _draw_key(self, canvas, keyname, opn, viewer):
        # synthesize a KeyEvent
        # TODO: this is hacky--see if we can rethink how this is handled
        #  so that we get passed an event similar to _draw_op()
        last_x, last_y = viewer.get_last_data_xy()
        event = KeyEvent(key=keyname, state='down', mode=self._mode,
                         modifiers=[], viewer=viewer,
                         data_x=last_x, data_y=last_y)

        return self._draw_op(canvas, event, last_x, last_y, opn, viewer)

    ##### DRAWING LOGIC #####

    def _draw_update(self, data_x, data_y, cxt):

        ## self.logger.debug("drawing a '%s' x,y=%f,%f" % (
        ##     self.t_drawtype, data_x, data_y))

        klass = self.draw_dict[self.t_drawtype]
        obj = None

        # update the context with current position
        x, y = cxt.crdmap.data_to(data_x, data_y)
        cxt.setvals(x=x, y=y, data_x=data_x, data_y=data_y)

        obj = klass.idraw(self, cxt)

        # elif self.t_drawtype == 'equilateraltriangle':
        #         len_x = self._start_x - x
        #         len_y = self._start_y - y
        #         length = max(abs(len_x), abs(len_y))
        #         obj = klass(self._start_x, self._start_y,
        #                     length, length, **self.t_drawparams)

        if obj is not None:
            obj.initialize(None, cxt.viewer, self.logger)
            #obj.initialize(None, cxt.viewer, viewer.logger)
            self._draw_obj = obj
            if time.time() - self._process_time > self._delta_time:
                self.process_drawing()

        return True

    def draw_start(self, canvas, event, data_x, data_y, viewer):
        if not self.candraw:
            return False

        self._draw_obj = None
        # get the drawing coordinate type (default 'data')
        crdtype = self.t_drawparams.get('coord', 'data')
        crdmap = viewer.get_coordmap(crdtype)
        x, y = crdmap.data_to(data_x, data_y)
        # create the drawing context
        self._draw_cxt = Bunch(start_x=x, start_y=y, points=[(x, y)],
                               x=x, y=y, data_x=data_x, data_y=data_y,
                               drawparams=self.t_drawparams,
                               crdmap=crdmap, viewer=viewer,
                               logger=self.logger)

        self._draw_update(data_x, data_y, self._draw_cxt)
        self.process_drawing()
        return True

    def draw_stop(self, canvas, event, data_x, data_y, viewer):
        if not self.candraw:
            return False

        self._draw_update(data_x, data_y, self._draw_cxt)
        obj, self._draw_obj = self._draw_obj, None

        if obj:
            objtag = self.add(obj)
            self.make_callback('draw-event', objtag)

            if self.edit_follows_draw:
                #self.set_draw_mode('edit')
                self.clear_selected()
                self.edit_select(obj)
                self.make_callback('edit-select', self._edit_obj)
            return True
        else:
            self.process_drawing()

    def draw_motion(self, canvas, event, data_x, data_y, viewer):
        if not self.candraw:
            return False

        self._draw_update(data_x, data_y, self._draw_cxt)
        return True

    def draw_poly_add(self, canvas, event, data_x, data_y, viewer):
        if not self.candraw:
            return False

        cxt = self._draw_cxt
        if self.t_drawtype in ('polygon', 'path'):
            x, y = cxt.crdmap.data_to(data_x, data_y)
            cxt.points.append((x, y))
        elif self.t_drawtype == 'beziercurve' and len(cxt.points) < 3:
            x, y = cxt.crdmap.data_to(data_x, data_y)
            cxt.points.append((x, y))
        return True

    def draw_poly_delete(self, canvas, event, data_x, data_y, viewer):
        if not self.candraw:
            return False

        cxt = self._draw_cxt
        if self.t_drawtype in ('polygon', 'path', 'beziercurve'):
            if len(cxt.points) > 0:
                cxt.points.pop()
        return True

    def is_drawing(self):
        return self._draw_obj is not None

    def enable_draw(self, tf):
        self.candraw = tf

    def set_drawcolor(self, colorname):
        self.t_drawparams['color'] = colorname

    def set_drawtype(self, drawtype, **drawparams):
        drawtype = drawtype.lower()
        assert drawtype in self.drawtypes, \
               ValueError("Bad drawing type '%s': must be one of %s" % (
            drawtype, self.drawtypes))
        self.t_drawtype = drawtype
        self.t_drawparams = drawparams.copy()

    def get_drawtypes(self):
        return self.drawtypes

    def get_drawtype(self):
        return self.t_drawtype

    def get_draw_class(self, drawtype):
        drawtype = drawtype.lower()
        klass = self.draw_dict[drawtype]
        return klass

    def get_drawparams(self):
        return self.t_drawparams.copy()

    def process_drawing(self):
        self._process_time = time.time()
        #viewer.redraw(whence=3)
        #self.redraw(whence=3)
        self.update_canvas()

    def register_canvas_type(self, name, klass):
        drawtype = name.lower()
        self.draw_dict[drawtype] = klass
        if not drawtype in self.drawtypes:
            self.drawtypes.append(drawtype)
            self.drawtypes.sort()


    ##### EDITING LOGIC #####

    def get_edit_object(self):
        return self._edit_obj

    def is_editing(self):
        return self.get_edit_obj() is not None

    def enable_edit(self, tf):
        self.canedit = tf

    def _edit_update(self, data_x, data_y, viewer):
        if (not self.canedit) or (self._cp_index is None):
            return False

        x, y = self._edit_obj.crdmap.data_to(data_x, data_y)

        if self._cp_index < 0:
            if self.easymove:
                ## self._edit_obj.move_to(x - self._start_x,
                ##                        y - self._start_y)
                self._edit_obj.set_edit_point(0, (x - self._start_x,
                                                  y - self._start_y))
        else:
            # special hack for objects that have rot_deg attribute
            if hasattr(self._edit_obj, 'rot_deg') and (self._cp_index > 0):
                rot_deg = - self._edit_obj.rot_deg
                xoff, yoff = self._edit_obj.get_center_pt()
                x, y = self._edit_obj.crdmap.rotate_pt(x, y, rot_deg,
                                                       xoff=xoff, yoff=yoff)

            self._edit_obj.set_edit_point(self._cp_index, (x, y))

        #self._edit_obj.sync_state()

        if time.time() - self._process_time > self._delta_time:
            self.process_drawing()
        return True

    def _is_editable(self, obj, x, y, is_inside):
        return is_inside and obj.editable

    def _prepare_to_move(self, obj, data_x, data_y):
        #print(("moving an object", obj.editable))
        self.edit_select(obj)
        self._cp_index = -1
        ref_x, ref_y = self._edit_obj.get_reference_pt()
        x, y = obj.crdmap.data_to(data_x, data_y)
        self._start_x, self._start_y = x - ref_x, y - ref_y
        #print(("end moving an object", obj.editable))

    def edit_start(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit:
            return False

        self._edit_tmp = self._edit_obj
        self._edit_status = False
        self._cp_index = None
        #shift_held = 'shift' in event.modifiers
        shift_held = False

        selects = self.get_selected()
        if len(selects) == 0:
            #print("no objects already selected")
            # <-- no objects already selected

            # check for objects at this location
            #print("getting items")
            objs = canvas.select_items_at(viewer, data_x, data_y,
                                          test=self._is_editable)
            #print("items: %s" % (str(objs)))

            if len(objs) == 0:
                # <-- no objects under cursor
                return False

            # pick top object
            obj = objs[-1]
            self._prepare_to_move(obj, data_x, data_y)

        else:
            self._edit_status = True

            # Ugh.  Check each selected object's control points
            # for a match
            contains = []
            for obj in selects:
                #print("editing: checking for cp")
                #edit_pts = self._edit_obj.get_edit_points()
                edit_pts = list(map(lambda pt: obj.crdmap.to_data(*pt),
                                    obj.get_edit_points()))
                #print((self._edit_obj, edit_pts))
                i = obj.get_pt(viewer, edit_pts, data_x, data_y,
                               obj.cap_radius)
                #print(('got point', i))
                if i is not None:
                    #print("editing cp #%d" % (i))
                    # editing a control point from an existing object
                    self._edit_obj = obj
                    self._cp_index = i
                    self._edit_update(data_x, data_y, viewer)
                    return True

                if obj.contains(data_x, data_y):
                    contains.append(obj)

            # <-- no control points match, is there an object that contains
            # this point?
            if len(contains) > 0:
                # TODO?: make a compound object of contains and move it?
                obj = contains[-1]
                if self.is_selected(obj) and shift_held:
                    # deselecting object
                    self.select_remove(obj)
                else:
                    self._prepare_to_move(obj, data_x, data_y)
                    ## Compound = self.get_draw_class('compoundobject')
                    ## c_obj = Compound(*self.get_selected())
                    ## c_obj.inherit_from(obj)
                    ## self._prepare_to_move(c_obj, data_x, data_y)

            else:
                # <-- user clicked outside any selected item's control pt
                # and outside any selected item
                if not shift_held:
                    self.clear_selected()

                # see now if there is an unselected item at this location
                objs = canvas.select_items_at(viewer, data_x, data_y,
                                              test=self._is_editable)
                #print("new items: %s" % (str(objs)))
                if len(objs) > 0:
                    # pick top object
                    obj = objs[-1]
                    #print(("top object", obj))
                    if self.num_selected() > 0:
                        #print("there are previously selected items")
                        # if there are already some selected items, then
                        # add this object to the selection, make a compound
                        # object
                        self.edit_select(obj)
                        Compound = self.get_draw_class('compoundobject')
                        c_obj = Compound(*self.get_selected())
                        c_obj.inherit_from(obj)
                        self._prepare_to_move(c_obj, data_x, data_y)
                    else:
                        # otherwise just start over with this new object
                        #print(("starting over"))
                        self._prepare_to_move(obj, data_x, data_y)

        self.process_drawing()
        return True

    def edit_stop(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit:
            return False

        if (self._edit_tmp != self._edit_obj) or (
            (self._edit_obj is not None) and
            (self._edit_status != self.is_selected(self._edit_obj))):
            # <-- editing status has changed
            #print("making edit-select callback")
            self.make_callback('edit-select', self._edit_obj)

        if (self._edit_obj is not None) and (self._cp_index is not None):
            # <-- an object has been edited
            self._edit_update(data_x, data_y, viewer)
            self._cp_index = None
            self.make_callback('edit-event', self._edit_obj)

        return True

    def edit_motion(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit:
            return False

        if (self._edit_obj is not None) and (self._cp_index is not None):
            self._edit_update(data_x, data_y, viewer)
            return True

        return False

    def edit_poly_add(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit:
            return False
        obj = self._edit_obj
        if (obj is not None) and self.is_selected(obj) and \
               (obj.kind in ('polygon', 'path')):
            self.logger.debug("checking points")
            # determine which line we are adding a point to
            points = list(obj.get_points())
            if obj.kind == 'polygon':
                points = points + [points[0]]
            x0, y0 = obj.crdmap.to_data(*points[0])
            insert = None
            for i in range(1, len(points[1:])):
                x1, y1 = obj.crdmap.to_data(*points[i])
                self.logger.debug("checking line %d" % (i))
                if obj.within_line(viewer, data_x, data_y, x0, y0, x1, y1,
                                   8):
                    insert = i
                    break
                x0, y0 = x1, y1
            if insert is not None:
                self.logger.debug("inserting point")
                # Point near a line
                x, y = obj.crdmap.data_to(data_x, data_y)
                points.insert(insert, (x, y))
                obj.points = points
                self.process_drawing()
            else:
                self.logger.debug("cursor not near a line")

        return True

    def edit_poly_delete(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit:
            return False
        obj = self._edit_obj
        if (obj is not None) and self.is_selected(obj) and \
               (obj.kind in ('polygon', 'path')):
            self.logger.debug("checking points")
            # determine which point we are deleting
            points = list(obj.get_points())
            delete = None
            for i in range(len(points)):
                x1, y1 = obj.crdmap.to_data(*points[i])
                self.logger.debug("checking vertex %d" % (i))
                if obj.within_radius(viewer, data_x, data_y, x1, y1,
                                     8):
                    delete = i
                    break
            if delete is not None:
                self.logger.debug("deleting point")
                points.pop(delete)
                obj.points = points
                self.process_drawing()
            else:
                self.logger.debug("cursor not near a point")

        return True

    def edit_rotate(self, delta_deg, viewer):
        if self._edit_obj is None:
            return False
        self._edit_obj.rotate_by(delta_deg)
        self.process_drawing()
        self.make_callback('edit-event', self._edit_obj)
        return True

    def _edit_rotate_cb(self, canvas, event, viewer, msg=True):
        if not self.canedit or (viewer != event.viewer):
            return False
        bd = viewer.get_bindings()
        amount = event.amount
        if bd.get_direction(event.direction) == 'down':
            amount = - amount
        return self.edit_rotate(amount)

    def edit_scale(self, delta_x, delta_y, viewer):
        if self._edit_obj is None:
            return False
        self._edit_obj.scale_by(delta_x, delta_y)
        self.process_drawing()
        self.make_callback('edit-event', self._edit_obj)
        return True

    def _edit_scale_cb(self, canvas, event, viewer, msg=True):
        if not self.canedit or (viewer != event.viewer):
            return False
        bd = viewer.get_bindings()
        if bd.get_direction(event.direction) == 'down':
            amount = 0.9
        else:
            amount = 1.1
        return self.edit_scale(amount, amount)

    def edit_delete(self):
        if (self._edit_obj is not None) and self.is_selected(self._edit_obj):
            self.select_remove(self._edit_obj)
            obj, self._edit_obj = self._edit_obj, None
            self.deleteObject(obj)
            self.make_callback('edit-event', self._edit_obj)
        return True

    def edit_delete_cb(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit or (viewer != event.viewer):
            return False
        return self.edit_delete()

    def edit_select(self, newobj):
        if not self.canedit:
            return False

        if not self.multi_select_ok:
            self.clear_selected()

        # add new object to selection
        self.select_add(newobj)
        self._edit_obj = newobj
        return True

    ##### SELECTION LOGIC #####

    def _is_selectable(self, obj, x, y, is_inside):
        return is_inside and obj.editable
        #return is_inside

    def is_selected(self, obj):
        return obj in self._selected

    def get_selected(self):
        return self._selected

    def num_selected(self):
        return len(self._selected)

    def clear_selected(self):
        self._selected = []

    def select_remove(self, obj):
        try:
            self._selected.remove(obj)
        except:
            pass

    def select_add(self, obj):
        if obj not in self._selected:
            self._selected.append(obj)

    def select_stop(self, canvas, button, data_x, data_y, viewer):
        #print("getting items")
        objs = canvas.select_items_at(viewer, data_x, data_y,
                                      test=self._is_selectable)
        if len(objs) == 0:
            # no objects
            return False

        # pick top object
        obj = objs[-1]

        if obj not in self._selected:
            self._selected.append(obj)
        else:
            self._selected.remove(obj)
            obj = None

        self.logger.debug("selected: %s" % (str(self._selected)))
        self.process_drawing()

        #self.make_callback('edit-select', obj, self._selected)
        return True

    def group_selection(self):
        Compound = self.get_draw_class('compoundobject')
        c_obj = Compound(self._selected)
        self._selected = [ comp_obj ]


    # The canvas drawing

    def draw(self, viewer):
        # Draw everything else as usual
        super(DrawingMixin, self).draw(viewer)

        # Draw our current drawing object, if any
        if self._draw_obj:
            self._draw_obj.draw(viewer)

        # Draw control points on edited objects
        # TODO: there is a problem if the object has been removed from
        # the canvas but not removed from the selection--we still end
        # up drawing the control points for it
        selected = self.get_selected()
        if len(selected) > 0:
            for obj in selected:
                cr = viewer.renderer.setup_cr(obj)
                obj.draw_edit(cr, viewer)


    ### NON-PEP8 EQUIVALENTS -- TO BE DEPRECATED ###

    setSurface = set_surface
    getSurface = get_surface
    getDrawClass = get_draw_class
Example #20
0
    def find_executable_obs_cb(self, widget):

        self.tree1.clear()
        self.view.update_pending()

        # get a handle to the control panel plugin
        cp = self.view.get_plugin('cp')
        use_db = cp.w.use_qdb.get_state()
        cp.update_scheduler(use_db=use_db)

        sdlr = self.model.get_scheduler()
        date_s = self.w.date.get_text().strip()
        time_b = self.w.start_time.get_text().strip()
        try:
            time_start = sdlr.site.get_date("%s %s" % (date_s, time_b))
        except Exception as e:
            errmsg = 'Error parsing start date/time:: {}\n'.format(str(e))
            errmsg += "\n".join([e.__class__.__name__, str(e)])
            self.logger.error(errmsg)
            self.controller.gui_do(self.controller.show_error, errmsg, raisetab=True)
            return

        # get the string for the date of observation in HST, which is what
        # is used in the Schedule table
        if time_start.hour < 9:
            date_obs_local = (time_start - timedelta(hours=10)).strftime("%Y-%m-%d")
        else:
            date_obs_local = time_start.strftime("%Y-%m-%d")
        self.logger.info("observation date (local) is '{}'".format(date_obs_local))

        # find the record in the schedule table that matches our date;
        # we need to get the list of filters and so on from it
        rec = None
        for _rec in sdlr.schedule_recs:
            if _rec.date == date_obs_local:
                rec = _rec
                break
        if rec is None:
            errmsg = "Can't find a record in the Schedule table matching '{}'".format(date_obs_local)
            self.logger.error(errmsg)
            self.controller.gui_do(self.controller.show_error, errmsg, raisetab=True)
            return

        len_s = self.w.len_time.get_text().strip()
        slot_length = max(0.0, float(len_s) * 60.0)

        data = Bunch(rec.data)
        # override some items from Schedule table
        data.cur_filter = self.w.filter.get_text().strip()
        data.cur_az = float(self.w.az.get_text().strip())
        data.cur_el = float(self.w.el.get_text().strip())
        data.seeing = float(self.w.seeing.get_text().strip())
        data.transparency = float(self.w.trans.get_text().strip())

        slot = entity.Slot(time_start, slot_length, data=data)
        self.slot = slot
        good, bad = sdlr.find_executable_obs(slot)

        tree_dict = OrderedDict()

        # Table header with units
        columns = [('Best', 'index'),
                   ('Program', 'program'),
                   ('OB Code', 'ob_code'),
                   ('Priority', 'priority'),
                   ('Grade', 'grade'),
                   ('Prep', 'prep'),
                   ('On Source', 'time'),
                   ('Target', 'target'),
                   ('Filter', 'filter'),
                   ('Delay', 'delay'),
                   ('Reason', 'reason')]

        self.tree1.setup_table(columns, 1, 'index')

        # This is to get around table widget not sorting numbers properly
        i_fmt = '{{0:0{0}d}}'.format(len(str(len(good))))

        # Table contents
        i = 1
        for rec in good:
            i_str = i_fmt.format(i)
            bnch = Bunch(index=i_str,
                         program=rec.ob.program.proposal,
                         ob_code=rec.ob.name,
                         priority=rec.ob.priority,
                         grade=rec.ob.program.grade,
                         prep="%.2f" % (rec.prep_sec / 60.0),
                         time="%.2f" % (rec.ob.total_time / 60.0),
                         target=rec.ob.target.name,
                         filter=rec.ob.inscfg.filter,
                         delay=rec.delay_sec / 60.0,
                         _group=good,
                         _rec=rec,
                         reason='OK')
            tree_dict[i_str] = bnch
            i += 1

        if self.show_bad:
            for rec in bad:
                i_str = i_fmt.format(i)
                bnch = Bunch(index=i_str,
                             program=rec.ob.program.proposal,
                             ob_code=rec.ob.name,
                             priority=rec.ob.priority,
                             grade=rec.ob.program.grade,
                             prep="%.2f" % (rec.prep_sec / 60.0),
                             time="%.2f" % (rec.ob.total_time / 60.0),
                             target=rec.ob.target.name,
                             filter=rec.ob.inscfg.filter,
                             delay=rec.delay_sec / 60.0,
                             _group=bad,
                             _rec=rec,
                             reason='NG: ' + rec.reason)
                tree_dict[i_str] = bnch
                i += 1

        self.tree1.set_tree(tree_dict)

        self.tree1.set_optimal_column_widths()
Example #21
0
                    dict(row=['ws', dict(name='channels', group=1)], stretch=1)
                ],
                [
                    'ws',
                    dict(name='right', width=350, group=2),
                    # (tabname, layout), ...
                    [("Dialogs", ['ws', dict(name='dialogs', group=2)])]
                ],
            ],
            stretch=1),
        dict(row=['hbox', dict(name='status')], stretch=0),
    ]
]

global_plugins = [
    Bunch(module='Pan', tab='_pan', ws='uleft', raisekey=None),
    Bunch(module='Info', tab='_info', ws='lleft', raisekey=None),
    Bunch(module='Header', tab='Header', ws='left', raisekey='H'),
    Bunch(module='Zoom', tab='Zoom', ws='left', raisekey='Z'),
    Bunch(module='Thumbs', tab='Thumbs', ws='right', raisekey='T'),
    Bunch(module='Contents', tab='Contents', ws='right', raisekey='c'),
    Bunch(module='WBrowser',
          tab='Help',
          ws='channels',
          raisekey='?',
          start=False),
    Bunch(module='Errors', tab='Errors', ws='right', start=True),
    Bunch(module='RC', tab='RC', ws='right', start=False),
    Bunch(module='SAMP', tab='SAMP', ws='right', start=False),
    Bunch(module='IRAF', tab='IRAF', ws='right', start=False),
    Bunch(module='Log', tab='Log', ws='right', start=False),
Example #22
0
def setup_SlitWavelength():
    return Bunch(path=os.path.join(os.path.split(__file__)[0], 'ginga_plugins.py'),
                 module='ginga_plugins', klass='SlitWavelength',
                 ptype='global', workspace='right', start=False,
                 category='PypeIt', menu='SlitWavelength', tab='SlitWavelength')
Example #23
0
    def update_scheduler(self, use_db=False, ignore_pgm_skip_flag=False):
        sdlr = self.model.get_scheduler()
        try:
            if use_db:
                if self.qdb is None:
                    self.connect_qdb()

            sdlr.set_weights(self.weights_qf.weights)
            sdlr.set_schedule_info(self.schedule_qf.schedule_info)
            pgms = self.programs_qf.programs_info
            sdlr.set_programs_info(pgms, ignore_pgm_skip_flag)
            self.logger.info('list of programs to be scheduled %s' %
                             sdlr.programs.keys())

            # TODO: this maybe should be done in the Model
            ob_keys = set([])
            ob_dict = {}
            propnames = list(self.programs_qf.programs_info.keys())
            okprops = []
            # Note: if the ignore_pgm_skip_flag is set to True, then
            # we don't pay attention to the "skip" flag in the
            # Programs sheet and thus consider all OB's in all
            # Programs. Otherwise, we do pay attention to the "skip"
            # flag and ignore all OB's in "skipped" programs.
            for propname in propnames:
                if not ignore_pgm_skip_flag and pgms[propname].skip:
                    self.logger.info(
                        'skip flag for program %s is set - skipping all OB in this program'
                        % propname)
                    continue

                if propname not in self.ob_info:
                    # If we haven't read these OBs in already, read them now
                    if use_db:
                        oblist = list(self.qq.get_obs_by_proposal(propname))

                    else:
                        if propname not in self.ob_qf_dict:
                            if not self.load_program(propname):
                                continue
                        oblist = self.ob_qf_dict[propname].obs_info

                    # cache the information about the OBs so we don't have
                    # to reconstruct it over and over
                    _key_lst = [(propname, ob.name) for ob in oblist]
                    _key_dct = dict(zip(_key_lst, oblist))

                    info = Bunch(oblist=oblist,
                                 obkeys=_key_lst,
                                 obdict=_key_dct)
                    self.ob_info[propname] = info

                info = self.ob_info[propname]

                okprops.append(propname)

                ob_keys = ob_keys.union(set(info.obkeys))
                ob_dict.update(info.obdict)

            self.logger.info("%s OBs after excluding skipped programs." %
                             (len(ob_keys)))

            do_not_execute = set([])
            props = {}

            # Remove keys for OBs that are already executed
            if use_db:
                self.logger.info("getting do not execute OB info")
                dne_obs, props = self.qq.get_do_not_execute_ob_info(okprops)

                do_not_execute = set(dne_obs)

            elif self.model.completed_obs is not None:
                do_not_execute = set(list(self.model.completed_obs.keys()))

                # Painful reconstruction of time already accumulated running the
                # programs for executed OBs.  Needed to inform scheduler so that
                # it can correctly calculate when to stop allocating OBs for a
                # program that has reached its time limit.
                props = {}
                for ob_key in do_not_execute:
                    (propid, obcode) = ob_key[:2]
                    bnch = props.setdefault(propid,
                                            Bunch(obcount=0, sched_time=0.0))
                    info = self.model.completed_obs[ob_key]
                    bnch.sched_time += info['acct_time']
                    bnch.obcount += 1

            sdlr.set_apriori_program_info(props)

            ob_keys -= do_not_execute
            self.logger.info("%s OBs after removing executed OBs." %
                             (len(ob_keys)))

            # for a deterministic result
            ob_keys = list(ob_keys)
            ob_keys.sort()

            # Now turn the keys back into actual OB list
            sdlr_oblist = [ob_dict[key] for key in ob_keys]

            # TODO: only needed if we ADD or REMOVE programs
            sdlr.set_oblist_info(sdlr_oblist)

        except Exception as e:
            errmsg = 'Error storing into scheduler: {}\n'.format(str(e))
            #self.logger.error("Error storing into scheduler: %s" % (str(e)))
            errmsg += "\n".join([e.__class__.__name__, str(e)])
            self.logger.error(errmsg)
            self.controller.gui_do(self.controller.show_error,
                                   errmsg,
                                   raisetab=True)
            raise e

        self.logger.info("scheduler initialized")
Example #24
0
                                 width=400, height=-1, group=2),
                      # (tabname, layout), ...
                      [("Dialogs", ['ws', dict(name='dialogs', wstype='tabs',
                                               group=2)
                                    ]
                        )]
                      ],
                     ], stretch=1),
                    dict(row=['ws', dict(name='toolbar', wstype='stack',
                                         height=40, group=2)],
                         stretch=0),
                    dict(row=['hbox', dict(name='status')], stretch=0),
                    ]]

global_plugins = [
    Bunch(module='Operations', workspace='operations', start=True,
          hidden=True, category='system'),
    Bunch(module='Toolbar', workspace='toolbar', start=True,
          hidden=True, category='system'),
    Bunch(module='Pan', workspace='uleft', start=True,
          hidden=True, category='system'),
    Bunch(module='Info', tab='Synopsis', workspace='lleft', start=True,
          hidden=True, category='system'),
    Bunch(module='Header', tab='Header', workspace='left', start=True,
          hidden=True, category='system'),
    Bunch(module='Zoom', tab='Zoom', workspace='left', start=True,
          hidden=True, category='system'),
    Bunch(module='Thumbs', tab='Thumbs', workspace='right', start=True,
          hidden=True, category='system'),
    Bunch(module='Contents', tab='Contents', workspace='right', start=True,
          hidden=True, category='system'),
    Bunch(module='Colorbar', workspace='cbar', start=True,
Example #25
0
 def add_local_plugin(self, module_name, ws_name, pfx=None):
     self.local_plugins.append(
         Bunch(module=module_name, ws=ws_name, pfx=pfx))
Example #26
0
 def add_local_plugin(self, module_name, ws_name,
                      path=None, klass=None, pfx=None, category=None):
     self.add_local_plugin_spec(
         Bunch(module=module_name, workspace=ws_name, category=category,
               path=path, klass=klass, pfx=pfx))
Example #27
0
def get_ginga_plugins(op_type):
    """Obtain relevant custom plugins from ``stginga`` and ``wss_tools``
    for the given QUIP operation type.

    Parameters
    ----------
    op_type : {'normalmode', 'segment_id', 'thumbnail'}
        QUIP operation type. Normal mode covers anything that is
        neither SEGMENT_ID nor THUMBNAIL.

    Returns
    -------
    global_plugins : list
        List of custom Ginga global plugins to load.

    local_plugins : list
        List of custom Ginga local plugins to load.

    """
    stg_pfx = 'stginga.plugins'
    wss_pfx = 'wss_tools.quip.plugins'
    global_plugins = [
        Bunch(module='AboutQUIP',
              tab='AboutQUIP',
              workspace='left',
              category='Custom',
              ptype='global',
              pfx=wss_pfx)
    ]

    if op_type == 'segment_id':
        local_plugins = []
        # Add special plugin for segment ID annotations
        global_plugins += [
            Bunch(module='SegIDHelper',
                  tab='SegIDHelper',
                  workspace='left',
                  category='Custom',
                  ptype='global',
                  pfx=wss_pfx)
        ]
    elif op_type == 'thumbnail':
        local_plugins = [
            Bunch(module='MosaicAuto',
                  workspace='dialogs',
                  category='Custom',
                  ptype='local',
                  pfx=wss_pfx)
        ]
    else:  # normalmode
        global_plugins += [
            Bunch(module='SaveQUIP',
                  tab='SaveQUIP',
                  workspace='right',
                  category='Custom',
                  ptype='global',
                  pfx=wss_pfx)
        ]
        local_plugins = [
            Bunch(module='BackgroundSub',
                  workspace='dialogs',
                  category='Custom',
                  ptype='local',
                  pfx=stg_pfx),
            Bunch(module='BadPixCorr',
                  workspace='dialogs',
                  category='Custom',
                  ptype='local',
                  pfx=stg_pfx),
            Bunch(module='DQInspect',
                  workspace='dialogs',
                  category='Custom',
                  ptype='local',
                  pfx=stg_pfx),
            Bunch(module='SNRCalc',
                  workspace='dialogs',
                  category='Custom',
                  ptype='local',
                  pfx=wss_pfx)
        ]

    return global_plugins, local_plugins
Example #28
0
class DrawingMixin(object):
    """The DrawingMixin is a mixin class that adds drawing capability for
    some of the basic CanvasObject-derived types.  The set_surface method is
    used to associate a ImageViewCanvas object for layering on.
    """

    def __init__(self):
        assert isinstance(self, CanvasMixin), "Missing CanvasMixin class"

        from .CanvasObject import drawCatalog
        # For interactive drawing
        self.candraw = False
        self.draw_dict = drawCatalog
        # canvas objects which we know how to draw have an "idraw"
        # class method
        self.drawtypes = [ key for key in self.draw_dict.keys()
                           if hasattr(self.draw_dict[key], 'idraw') ]
        self.drawtypes.sort()
        self.t_drawtype = 'point'
        self.t_drawparams = {}
        # holds the drawing context
        self._draw_cxt = None

        # For interactive editing
        self.canedit = False
        # Set to False to disable drag moves except from move control pt
        self.easymove = True
        self._start_x = 0
        self._start_y = 0
        self._cp_index = None
        self._edit_obj = None
        self._edit_status = False
        self._edit_detail = {}
        self._pick_cur_obj = None

        # For modes
        self._mode = 'draw'
        self._mode_tbl = Bunch()
        self.add_draw_mode(None)
        self.add_draw_mode('draw', down=self.draw_start,
                           move=self.draw_motion, up=self.draw_stop,
                           poly_add=self.draw_poly_add,
                           poly_delete=self.draw_poly_delete)
        self.add_draw_mode('edit', down=self.edit_start,
                           move=self.edit_motion, up=self.edit_stop,
                           poly_add=self.edit_poly_add,
                           poly_delete=self.edit_poly_delete)
        self.add_draw_mode('pick', down=self.pick_start,
                           move=self.pick_motion, up=self.pick_stop,
                           hover=self.pick_hover,
                           poly_add=self.edit_poly_add,
                           poly_delete=self.edit_poly_delete)

        # For selection
        self._selected = []
        self.multi_select_ok = False

        # this controls whether an object is automatically selected for
        # editing immediately after being drawn
        self.edit_follows_draw = False

        self._process_time = 0.0
        # time delta threshold for deciding whether to update the image
        self._delta_time = 0.020
        self._draw_obj = None

        # NOTE: must be mixed in with a Callback.Callbacks
        for name in ('draw-event', 'draw-down', 'draw-move', 'draw-up',
                     'cursor-down', 'cursor-up', 'cursor-move',
                     'draw-scroll', 'keydown-poly_add', 'keydown-poly_del',
                     'keydown-edit_del', 'edit-event',
                     'edit-select', 'drag-drop', 'cursor-changed'):
            self.enable_callback(name)

    def set_surface(self, viewer):
        self.viewer = viewer

        # Register this canvas for events of interest.
        # Assumes we are mixed in with a canvas
        canvas = self

        # for legacy drawing via draw mode in Bindmap
        canvas.add_callback('draw-down', self.draw_start, viewer)
        canvas.add_callback('draw-move', self.draw_motion, viewer)
        canvas.add_callback('draw-up', self.draw_stop, viewer)

        canvas.add_callback('key-press', self._draw_key, 'key', viewer)
        canvas.add_callback('keydown-poly_add', self._draw_op, 'poly_add',
                          viewer)
        canvas.add_callback('keydown-poly_del', self._draw_op, 'poly_delete',
                          viewer)
        canvas.add_callback('keydown-edit_del', self.edit_delete_cb, viewer)
        #canvas.add_callback('draw-scroll', self._edit_rotate_cb, viewer)
        #canvas.add_callback('draw-scroll', self._edit_scale_cb, viewer)

    def register_for_cursor_drawing(self, viewer):
        canvas = self
        canvas.add_callback('cursor-down', self._draw_op, 'down', viewer)
        canvas.add_callback('cursor-move', self._draw_op, 'move', viewer)
        canvas.add_callback('cursor-up', self._draw_op, 'up', viewer)
        canvas.set_callback('none-move', self._draw_op, 'hover', viewer)

    ##### MODE LOGIC #####

    def add_draw_mode(self, name, **kwargs):
        try:
            bnch = self._mode_tbl[name]
        except KeyError:
            bnch = Bunch(name=name, **kwargs)
            self._mode_tbl[name] = bnch

        return bnch

    def set_draw_mode(self, mode):
        if not mode in self._mode_tbl:
            modes = list(self._mode_tbl.keys())
            raise ValueError("mode must be one of: %s" % (str(modes)))

        self._mode = mode
        if mode != 'edit':
            self.clear_selected()

        self.update_canvas()

    def get_draw_mode(self):
        return self._mode

    def _draw_op(self, canvas, event, data_x, data_y, opn, viewer):
        if viewer != event.viewer:
            return False

        mode = self._mode
        # Hack to handle legacy drawing using draw mode in Bindmap
        if self.is_drawing():
            mode = 'draw'

        try:
            method = self._mode_tbl[mode][opn]
        except KeyError:
            return False

        if method is not None:
            return method(canvas, event, data_x, data_y, viewer)
        return False

    def _draw_key(self, canvas, keyname, opn, viewer):
        # synthesize a KeyEvent
        # TODO: this is hacky--see if we can rethink how this is handled
        #  so that we get passed an event similar to _draw_op()
        last_x, last_y = viewer.get_last_data_xy()
        event = KeyEvent(key=keyname, state='down', mode=self._mode,
                         modifiers=[], viewer=viewer,
                         data_x=last_x, data_y=last_y)

        return self._draw_op(canvas, event, last_x, last_y, opn, viewer)

    ##### DRAWING LOGIC #####

    def _draw_update(self, data_x, data_y, cxt, force_update=False):

        obj = None

        # update the context with current position
        x, y = cxt.crdmap.data_to(data_x, data_y)
        cxt.setvals(x=x, y=y, data_x=data_x, data_y=data_y)

        draw_class = cxt.draw_class
        if draw_class is None:
            return False

        obj = draw_class.idraw(self, cxt)

        # update display every delta_time secs
        if obj is not None:
            obj.initialize(self, cxt.viewer, self.logger)
            self._draw_obj = obj
            if force_update or (time.time() - self._process_time > self._delta_time):
                self.process_drawing()

        return True

    def draw_start(self, canvas, event, data_x, data_y, viewer):
        if not self.candraw:
            return False

        self._draw_obj = None
        self.clear_selected()

        # get the drawing coordinate type (default 'data')
        crdtype = self.t_drawparams.get('coord', 'data')
        crdmap = viewer.get_coordmap(crdtype)
        x, y = crdmap.data_to(data_x, data_y)

        klass = self.draw_dict.get(self.t_drawtype, None)

        # create the drawing context
        self._draw_cxt = Bunch(start_x=x, start_y=y, points=[(x, y)],
                               x=x, y=y, data_x=data_x, data_y=data_y,
                               drawparams=self.t_drawparams,
                               crdmap=crdmap, viewer=viewer,
                               draw_class=klass, logger=self.logger)

        self._draw_update(data_x, data_y, self._draw_cxt, force_update=True)
        return True

    def draw_stop(self, canvas, event, data_x, data_y, viewer):
        if not self.candraw:
            return False

        self._draw_update(data_x, data_y, self._draw_cxt)
        obj, self._draw_obj = self._draw_obj, None

        if obj is not None:
            objtag = self.add(obj)
            self.make_callback('draw-event', objtag)

            if self.edit_follows_draw:
                #self.set_draw_mode('edit')
                self.edit_select(obj)
                self.make_callback('edit-select', self._edit_obj)
            return True
        else:
            self.process_drawing()

    def draw_motion(self, canvas, event, data_x, data_y, viewer):
        if not self.candraw:
            return False

        self._draw_update(data_x, data_y, self._draw_cxt)
        return True

    def draw_poly_add(self, canvas, event, data_x, data_y, viewer):
        if not self.candraw:
            return False

        cxt = self._draw_cxt
        if self.t_drawtype in ('polygon', 'freepolygon', 'path', 'freepath'):
            x, y = cxt.crdmap.data_to(data_x, data_y)
            cxt.points.append((x, y))
        elif self.t_drawtype == 'beziercurve' and len(cxt.points) < 3:
            x, y = cxt.crdmap.data_to(data_x, data_y)
            cxt.points.append((x, y))

        self._draw_update(data_x, data_y, cxt, force_update=True)
        return True

    def draw_poly_delete(self, canvas, event, data_x, data_y, viewer):
        if not self.candraw:
            return False

        cxt = self._draw_cxt
        if self.t_drawtype in ('polygon', 'freepolygon', 'path',
                               'freepath', 'beziercurve'):
            if len(cxt.points) > 0:
                cxt.points.pop()

        self._draw_update(data_x, data_y, cxt, force_update=True)
        return True

    def is_drawing(self):
        return self._draw_obj is not None

    def enable_draw(self, tf):
        self.candraw = tf

    def set_drawcolor(self, colorname):
        self.t_drawparams['color'] = colorname

    def set_drawtype(self, drawtype, **drawparams):
        if drawtype is not None:
            drawtype = drawtype.lower()
            assert drawtype in self.drawtypes, \
                   ValueError("Bad drawing type '%s': must be one of %s" % (
                drawtype, self.drawtypes))
        self.t_drawtype = drawtype
        self.t_drawparams = drawparams.copy()

    def get_drawtypes(self):
        return self.drawtypes

    def get_drawtype(self):
        return self.t_drawtype

    def get_draw_class(self, drawtype):
        drawtype = drawtype.lower()
        klass = self.draw_dict[drawtype]
        return klass

    def get_drawparams(self):
        return self.t_drawparams.copy()

    def process_drawing(self):
        self._process_time = time.time()
        #self.redraw(whence=3)
        self.update_canvas()

    def register_canvas_type(self, name, klass):
        drawtype = name.lower()
        self.draw_dict[drawtype] = klass
        if not drawtype in self.drawtypes:
            self.drawtypes.append(drawtype)
            self.drawtypes.sort()


    ##### EDITING LOGIC #####

    def get_edit_object(self):
        return self._edit_obj

    def is_editing(self):
        return self.get_edit_obj() is not None

    def enable_edit(self, tf):
        self.canedit = tf

    def _rot_xlate(self, obj, data_x, data_y):
        # translate point back into non-rotated form
        rot_deg = - obj.rot_deg
        xoff, yoff = obj.get_center_pt()
        data_x, data_y = trcalc.rotate_pt(data_x, data_y, rot_deg,
                                          xoff=xoff, yoff=yoff)
        return data_x, data_y

    def _edit_update(self, data_x, data_y, viewer):
        if (not self.canedit) or (self._cp_index is None):
            return False

        x, y = data_x, data_y

        if self._cp_index < 0:
            if self.easymove:
                self._edit_obj.set_edit_point(0, (x - self._start_x,
                                                  y - self._start_y),
                                              self._edit_detail)
        else:
            # special hack for objects that have rot_deg attribute
            if hasattr(self._edit_obj, 'rot_deg') and (self._cp_index > 0):
                x, y = self._rot_xlate(self._edit_obj, x, y)

            self._edit_obj.set_edit_point(self._cp_index, (x, y),
                                          self._edit_detail)

        #self._edit_obj.sync_state()

        if time.time() - self._process_time > self._delta_time:
            self.process_drawing()
        return True

    def _is_editable(self, obj, x, y, is_inside):
        return is_inside and obj.editable

    def _prepare_to_move(self, obj, data_x, data_y):
        #print(("moving an object", obj.editable))
        self.edit_select(obj)
        self._cp_index = -1
        ref_x, ref_y = self._edit_obj.get_reference_pt()
        self._start_x, self._start_y = data_x - ref_x, data_y - ref_y
        #print(("end moving an object", obj.editable))

    def edit_start(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit:
            return False

        self._edit_tmp = self._edit_obj
        self._edit_status = False
        self._edit_detail = Bunch()
        self._cp_index = None
        #shift_held = 'shift' in event.modifiers
        shift_held = False

        selects = self.get_selected()
        if len(selects) == 0:
            #print("no objects already selected")
            # <-- no objects already selected

            # check for objects at this location
            #print("getting items")
            objs = canvas.select_items_at(viewer, data_x, data_y,
                                          test=self._is_editable)
            #print("items: %s" % (str(objs)))

            if len(objs) == 0:
                # <-- no objects under cursor
                return False

            # pick top object
            obj = objs[-1]
            self._prepare_to_move(obj, data_x, data_y)

        else:
            self._edit_status = True

            # Ugh.  Check each selected object's control points
            # for a match
            contains = []
            for obj in selects:
                #print("editing: checking for cp")
                edit_pts = obj.get_edit_points(viewer)
                #print((self._edit_obj, edit_pts))
                i = obj.get_pt(viewer, edit_pts, data_x, data_y,
                               obj.cap_radius)
                #print(('got point', i))
                if i is not None:
                    #print("editing cp #%d" % (i))
                    # editing a control point from an existing object
                    self._edit_obj = obj
                    self._cp_index = i
                    if hasattr(obj, 'rot_deg'):
                        x, y = self._rot_xlate(self._edit_obj, data_x, data_y)
                    else:
                        x, y = data_x, data_y
                    self._edit_detail.start_pos = (x, y)
                    obj.setup_edit(self._edit_detail)
                    self._edit_update(data_x, data_y, viewer)
                    return True

                ## if obj.contains(data_x, data_y):
                ##     contains.append(obj)
                # update: check if objects bbox contains this point
                x1, y1, x2, y2 = obj.get_llur()
                if (x1 <= data_x <= x2) and (y1 <= data_y <= y2):
                    contains.append(obj)

            # <-- no control points match, is there an object that contains
            # this point?
            if len(contains) > 0:
                # TODO?: make a compound object of contains and move it?
                obj = contains[-1]
                if self.is_selected(obj) and shift_held:
                    # deselecting object
                    self.select_remove(obj)
                else:
                    self._prepare_to_move(obj, data_x, data_y)
                    ## Compound = self.get_draw_class('compoundobject')
                    ## c_obj = Compound(*self.get_selected())
                    ## c_obj.inherit_from(obj)
                    ## self._prepare_to_move(c_obj, data_x, data_y)

            else:
                # <-- user clicked outside any selected item's control pt
                # and outside any selected item
                if not shift_held:
                    self.clear_selected()

                # see now if there is an unselected item at this location
                objs = canvas.select_items_at(viewer, data_x, data_y,
                                              test=self._is_editable)
                #print("new items: %s" % (str(objs)))
                if len(objs) > 0:
                    # pick top object
                    obj = objs[-1]
                    #print(("top object", obj))
                    if self.num_selected() > 0:
                        #print("there are previously selected items")
                        # if there are already some selected items, then
                        # add this object to the selection, make a compound
                        # object
                        self.edit_select(obj)
                        Compound = self.get_draw_class('compoundobject')
                        c_obj = Compound(*self.get_selected())
                        c_obj.inherit_from(obj)
                        self._prepare_to_move(c_obj, data_x, data_y)
                    else:
                        # otherwise just start over with this new object
                        #print(("starting over"))
                        self._prepare_to_move(obj, data_x, data_y)

        self.process_drawing()
        return True

    def edit_stop(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit:
            return False

        if (self._edit_tmp != self._edit_obj) or (
            (self._edit_obj is not None) and
            (self._edit_status != self.is_selected(self._edit_obj))):
            # <-- editing status has changed
            #print("making edit-select callback")
            self.make_callback('edit-select', self._edit_obj)

        if (self._edit_obj is not None) and (self._cp_index is not None):
            # <-- an object has been edited
            self._edit_update(data_x, data_y, viewer)
            self._cp_index = None
            self.make_callback('edit-event', self._edit_obj)
            self._edit_obj.make_callback('edited')

        return True

    def edit_motion(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit:
            return False

        if (self._edit_obj is not None) and (self._cp_index is not None):
            self._edit_update(data_x, data_y, viewer)
            return True

        return False

    def edit_poly_add(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit:
            return False
        obj = self._edit_obj
        if (obj is not None) and self.is_selected(obj) and \
               (obj.kind in ('polygon', 'path')):
            self.logger.debug("checking points")
            # determine which line we are adding a point to
            points = list(obj.get_data_points())
            if obj.kind == 'polygon':
                points = points + [points[0]]
            x0, y0 = points[0]
            insert = None
            for i in range(1, len(points[1:])+1):
                x1, y1 = points[i]
                self.logger.debug("checking line %d" % (i))
                if obj.within_line(viewer, data_x, data_y, x0, y0, x1, y1,
                                   8):
                    insert = i
                    break
                x0, y0 = x1, y1
            if insert is not None:
                self.logger.debug("inserting point")
                # Point near a line
                pt = obj.crdmap.data_to(data_x, data_y)
                obj.insert_pt(insert, pt)
                self.process_drawing()
            else:
                self.logger.debug("cursor not near a line")

        return True

    def edit_poly_delete(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit:
            return False
        obj = self._edit_obj
        if (obj is not None) and self.is_selected(obj) and \
               (obj.kind in ('polygon', 'path')):
            self.logger.debug("checking points")
            # determine which point we are deleting
            points = list(obj.get_data_points())
            delete = None
            for i in range(len(points)):
                x1, y1 = points[i]
                self.logger.debug("checking vertex %d" % (i))
                if obj.within_radius(viewer, data_x, data_y, x1, y1,
                                     8):
                    delete = i
                    break
            if delete is not None:
                self.logger.debug("deleting point")
                obj.delete_pt(delete)
                self.process_drawing()
            else:
                self.logger.debug("cursor not near a point")

        return True

    def edit_rotate(self, delta_deg, viewer):
        if self._edit_obj is None:
            return False
        self._edit_obj.rotate_by(delta_deg)
        self.process_drawing()
        self.make_callback('edit-event', self._edit_obj)
        return True

    def _edit_rotate_cb(self, canvas, event, viewer, msg=True):
        if not self.canedit or (viewer != event.viewer):
            return False
        bd = viewer.get_bindings()
        amount = event.amount
        if bd.get_direction(event.direction) == 'down':
            amount = - amount
        return self.edit_rotate(amount)

    def edit_scale(self, delta_x, delta_y, viewer):
        if self._edit_obj is None:
            return False
        self._edit_obj.scale_by(delta_x, delta_y)
        self.process_drawing()
        self.make_callback('edit-event', self._edit_obj)
        return True

    def _edit_scale_cb(self, canvas, event, viewer, msg=True):
        if not self.canedit or (viewer != event.viewer):
            return False
        bd = viewer.get_bindings()
        if bd.get_direction(event.direction) == 'down':
            amount = 0.9
        else:
            amount = 1.1
        return self.edit_scale(amount, amount)

    def edit_delete(self):
        if (self._edit_obj is not None) and self.is_selected(self._edit_obj):
            self.select_remove(self._edit_obj)
            obj, self._edit_obj = self._edit_obj, None
            self.delete_object(obj)
            self.make_callback('edit-event', self._edit_obj)
        return True

    def edit_delete_cb(self, canvas, event, data_x, data_y, viewer):
        if not self.canedit or (viewer != event.viewer):
            return False
        return self.edit_delete()

    def edit_select(self, newobj):
        if not self.canedit:
            return False

        if not self.multi_select_ok:
            self.clear_selected()

        # add new object to selection
        self.select_add(newobj)
        self._edit_obj = newobj
        return True

    ##### SELECTION LOGIC #####

    def _is_selectable(self, obj, x, y, is_inside):
        return is_inside and obj.editable
        #return is_inside

    def is_selected(self, obj):
        return obj in self._selected

    def get_selected(self):
        return self._selected

    def num_selected(self):
        return len(self._selected)

    def clear_selected(self):
        self._selected = []

    def select_remove(self, obj):
        try:
            self._selected.remove(obj)
        except:
            pass

    def select_add(self, obj):
        if obj not in self._selected:
            self._selected.append(obj)

    ##### PICK LOGIC #####

    def _do_pick(self, canvas, event, data_x, data_y, cb_name, viewer):
        # check for objects at this location
        objs = canvas.select_items_at(viewer, data_x, data_y)

        if len(objs) == 0:
            # <-- no objects under cursor

            if self._pick_cur_obj is not None:
                # leaving an object that we were in--make pick-leave cb
                obj, self._pick_cur_obj = self._pick_cur_obj, None
                pt = obj.crdmap.data_to(data_x, data_y)
                obj.make_callback('pick-leave', canvas, event, pt)

            return False

        # pick top object
        obj = objs[-1]
        self.logger.debug("%s event in %s obj at x, y = %d, %d" % (
            cb_name, obj.kind, data_x, data_y))

        # get coordinates in native form for this object
        pt = obj.crdmap.data_to(data_x, data_y)

        if self._pick_cur_obj is None:
            # entering a new object--make pick-enter cb
            self._pick_cur_obj = obj
            obj.make_callback('pick-enter', canvas, event, pt)

        # make pick callback
        obj.make_callback(cb_name, canvas, event, pt)
        return True

    def pick_start(self, canvas, event, data_x, data_y, viewer):
        return self._do_pick(canvas, event, data_x, data_y,
                             'pick-down', viewer)

    def pick_motion(self, canvas, event, data_x, data_y, viewer):
        return self._do_pick(canvas, event, data_x, data_y,
                             'pick-move', viewer)

    def pick_hover(self, canvas, event, data_x, data_y, viewer):
        return self._do_pick(canvas, event, data_x, data_y,
                             'pick-hover', viewer)

    def pick_stop(self, canvas, event, data_x, data_y, viewer):
        return self._do_pick(canvas, event, data_x, data_y,
                             'pick-up', viewer)


    # The canvas drawing

    def draw(self, viewer):
        # Draw everything else as usual
        super(DrawingMixin, self).draw(viewer)

        # Draw our current drawing object, if any
        if self._draw_obj:
            self._draw_obj.draw(viewer)

        # Draw control points on edited objects
        selected = list(self.get_selected())
        if len(selected) > 0:
            for obj in selected:
                cr = viewer.renderer.setup_cr(obj)
                obj.draw_edit(cr, viewer)


    ### NON-PEP8 EQUIVALENTS -- TO BE DEPRECATED ###

    setSurface = set_surface
    getDrawClass = get_draw_class
Example #29
0
    def main(self, options, args):
        """
        Main routine for running the reference viewer.

        `options` is a OptionParser object that has been populated with
        values from parsing the command line.  It should at least include
        the options from add_default_options()

        `args` is a list of arguments to the viewer after parsing out
        options.  It should contain a list of files or URLs to load.
        """

        # Create a logger
        logger = log.get_logger(name='ginga', options=options)

        # Get settings (preferences)
        basedir = paths.ginga_home
        if not os.path.exists(basedir):
            try:
                os.mkdir(basedir)
            except OSError as e:
                logger.warning("Couldn't create ginga settings area (%s): %s" %
                               (basedir, str(e)))
                logger.warning("Preferences will not be able to be saved")

        # Set up preferences
        prefs = Settings.Preferences(basefolder=basedir, logger=logger)
        settings = prefs.create_category('general')
        settings.set_defaults(useMatplotlibColormaps=False,
                              widgetSet='choose',
                              WCSpkg='choose',
                              FITSpkg='choose',
                              recursion_limit=2000,
                              icc_working_profile=None,
                              font_scaling_factor=None,
                              save_layout=True,
                              channel_prefix="Image")
        settings.load(onError='silent')

        # default of 1000 is a little too small
        sys.setrecursionlimit(settings.get('recursion_limit'))

        # So we can find our plugins
        sys.path.insert(0, basedir)
        package_home = os.path.split(sys.modules['ginga.version'].__file__)[0]
        child_dir = os.path.join(package_home, 'rv', 'plugins')
        sys.path.insert(0, child_dir)
        plugin_dir = os.path.join(basedir, 'plugins')
        sys.path.insert(0, plugin_dir)

        gc = os.path.join(basedir, "ginga_config.py")
        have_ginga_config = os.path.exists(gc)

        # User configuration, earliest possible intervention
        if have_ginga_config:
            try:
                import ginga_config

                if hasattr(ginga_config, 'init_config'):
                    ginga_config.init_config(self)

            except Exception as e:
                try:
                    (type, value, tb) = sys.exc_info()
                    tb_str = "\n".join(traceback.format_tb(tb))

                except Exception:
                    tb_str = "Traceback information unavailable."

                logger.error("Error processing Ginga config file: %s" %
                             (str(e)))
                logger.error("Traceback:\n%s" % (tb_str))

        # Choose a toolkit
        if options.toolkit:
            toolkit = options.toolkit
        else:
            toolkit = settings.get('widgetSet', 'choose')

        if toolkit == 'choose':
            try:
                ginga_toolkit.choose()
            except ImportError as e:
                print("UI toolkit choose error: %s" % str(e))
                sys.exit(1)
        else:
            ginga_toolkit.use(toolkit)

        tkname = ginga_toolkit.get_family()
        logger.info("Chosen toolkit (%s) family is '%s'" %
                    (ginga_toolkit.toolkit, tkname))

        # these imports have to be here, otherwise they force the choice
        # of toolkit too early
        from ginga.rv.Control import GingaShell, GuiLogHandler

        if settings.get('useMatplotlibColormaps', False):
            # Add matplotlib color maps if matplotlib is installed
            try:
                from ginga import cmap
                cmap.add_matplotlib_cmaps(fail_on_import_error=False)
            except Exception as e:
                logger.warning("failed to load matplotlib colormaps: %s" %
                               (str(e)))

        # Set a working RGB ICC profile if user has one
        working_profile = settings.get('icc_working_profile', None)
        rgb_cms.working_profile = working_profile

        # User wants to customize the WCS package?
        if options.wcspkg:
            wcspkg = options.wcspkg
        else:
            wcspkg = settings.get('WCSpkg', 'choose')

        try:
            from ginga.util import wcsmod
            if wcspkg != 'choose':
                assert wcsmod.use(wcspkg) is True
        except Exception as e:
            logger.warning("failed to set WCS package preference: %s" %
                           (str(e)))

        # User wants to customize the FITS package?
        if options.fitspkg:
            fitspkg = options.fitspkg
        else:
            fitspkg = settings.get('FITSpkg', 'choose')

        try:
            from ginga.util import io_fits, loader
            if fitspkg != 'choose':
                assert io_fits.use(fitspkg) is True
                # opener name is not necessarily the same
                opener = loader.get_opener(io_fits.fitsLoaderClass.name)
                # set this opener as the priority one
                opener.priority = -99

        except Exception as e:
            logger.warning("failed to set FITS package preference: %s" %
                           (str(e)))

        # Check whether user wants to use OpenCv
        use_opencv = settings.get('use_opencv', False)
        if use_opencv or options.opencv:
            from ginga import trcalc
            try:
                trcalc.use('opencv')
            except Exception as e:
                logger.warning("failed to set OpenCv preference: %s" %
                               (str(e)))

        # Check whether user wants to use OpenCL
        use_opencl = settings.get('use_opencl', False)
        if use_opencl or options.opencl:
            from ginga import trcalc
            try:
                trcalc.use('opencl')
            except Exception as e:
                logger.warning("failed to set OpenCL preference: %s" %
                               (str(e)))

        # Create the dynamic module manager
        mm = ModuleManager.ModuleManager(logger)

        # Create and start thread pool
        ev_quit = threading.Event()
        thread_pool = Task.ThreadPool(options.numthreads,
                                      logger,
                                      ev_quit=ev_quit)
        thread_pool.startall()

        # Create the Ginga main object
        ginga_shell = GingaShell(logger,
                                 thread_pool,
                                 mm,
                                 prefs,
                                 ev_quit=ev_quit)

        # user wants to set font scaling.
        # NOTE: this happens *after* creation of shell object, since
        # Application object constructor will also set this
        font_scaling = settings.get('font_scaling_factor', None)
        if font_scaling is not None:
            logger.debug(
                "overriding font_scaling_factor to {}".format(font_scaling))
            from ginga.fonts import font_asst
            font_asst.default_scaling_factor = font_scaling

        layout_file = None
        if not options.norestore and settings.get('save_layout', False):
            layout_file = os.path.join(basedir, 'layout')

        ginga_shell.set_layout(self.layout, layout_file=layout_file)

        # User configuration (custom star catalogs, etc.)
        if have_ginga_config:
            try:
                if hasattr(ginga_config, 'pre_gui_config'):
                    ginga_config.pre_gui_config(ginga_shell)
            except Exception as e:
                try:
                    (type, value, tb) = sys.exc_info()
                    tb_str = "\n".join(traceback.format_tb(tb))

                except Exception:
                    tb_str = "Traceback information unavailable."

                logger.error("Error importing Ginga config file: %s" %
                             (str(e)))
                logger.error("Traceback:\n%s" % (tb_str))

        # Build desired layout
        ginga_shell.build_toplevel()

        # Did user specify a particular geometry?
        if options.geometry:
            ginga_shell.set_geometry(options.geometry)

        # make the list of disabled plugins
        if options.disable_plugins is not None:
            disabled_plugins = options.disable_plugins.lower().split(',')
        else:
            disabled_plugins = settings.get('disable_plugins', [])
            if not isinstance(disabled_plugins, list):
                disabled_plugins = disabled_plugins.lower().split(',')

        # Add GUI log handler (for "Log" global plugin)
        guiHdlr = GuiLogHandler(ginga_shell)
        guiHdlr.setLevel(options.loglevel)
        fmt = logging.Formatter(log.LOG_FORMAT)
        guiHdlr.setFormatter(fmt)
        logger.addHandler(guiHdlr)

        # Load any custom modules
        if options.modules is not None:
            modules = options.modules.split(',')
        else:
            modules = settings.get('global_plugins', [])
            if not isinstance(modules, list):
                modules = modules.split(',')

        for long_plugin_name in modules:
            if '.' in long_plugin_name:
                tmpstr = long_plugin_name.split('.')
                plugin_name = tmpstr[-1]
                pfx = '.'.join(tmpstr[:-1])
            else:
                plugin_name = long_plugin_name
                pfx = None
            menu_name = "%s [G]" % (plugin_name)
            spec = Bunch(name=plugin_name,
                         module=plugin_name,
                         ptype='global',
                         tab=plugin_name,
                         menu=menu_name,
                         category="Custom",
                         workspace='right',
                         pfx=pfx)
            self.add_plugin_spec(spec)

        # Load any custom local plugins
        if options.plugins is not None:
            plugins = options.plugins.split(',')
        else:
            plugins = settings.get('local_plugins', [])
            if not isinstance(plugins, list):
                plugins = plugins.split(',')

        for long_plugin_name in plugins:
            if '.' in long_plugin_name:
                tmpstr = long_plugin_name.split('.')
                plugin_name = tmpstr[-1]
                pfx = '.'.join(tmpstr[:-1])
            else:
                plugin_name = long_plugin_name
                pfx = None
            spec = Bunch(module=plugin_name,
                         workspace='dialogs',
                         ptype='local',
                         category="Custom",
                         hidden=False,
                         pfx=pfx)
            self.add_plugin_spec(spec)

        # Add non-disabled plugins
        enabled_plugins = [
            spec for spec in self.plugins
            if spec.module.lower() not in disabled_plugins
        ]
        ginga_shell.set_plugins(enabled_plugins)

        # start any plugins that have start=True
        ginga_shell.boot_plugins()
        ginga_shell.update_pending()

        # TEMP?
        tab_names = [
            name.lower() for name in ginga_shell.ds.get_tabnames(group=None)
        ]
        if 'info' in tab_names:
            ginga_shell.ds.raise_tab('Info')
        if 'synopsis' in tab_names:
            ginga_shell.ds.raise_tab('Synopsis')
        if 'thumbs' in tab_names:
            ginga_shell.ds.raise_tab('Thumbs')

        # Add custom channels
        if options.channels is not None:
            channels = options.channels.split(',')
        else:
            channels = settings.get('channels', self.channels)
            if not isinstance(channels, list):
                channels = channels.split(',')

        if len(channels) == 0:
            # should provide at least one default channel?
            channels = [settings.get('channel_prefix', "Image")]

        # populate the initial channel lineup
        for item in channels:
            if isinstance(item, str):
                chname, wsname = item, None
            else:
                chname, wsname = item
            ginga_shell.add_channel(chname, workspace=wsname)

        ginga_shell.change_channel(chname)

        # User configuration (custom star catalogs, etc.)
        if have_ginga_config:
            try:
                if hasattr(ginga_config, 'post_gui_config'):
                    ginga_config.post_gui_config(ginga_shell)

            except Exception as e:
                try:
                    (type, value, tb) = sys.exc_info()
                    tb_str = "\n".join(traceback.format_tb(tb))

                except Exception:
                    tb_str = "Traceback information unavailable."

                logger.error("Error processing Ginga config file: %s" %
                             (str(e)))
                logger.error("Traceback:\n%s" % (tb_str))

        # Redirect warnings to logger
        for hdlr in logger.handlers:
            logging.getLogger('py.warnings').addHandler(hdlr)

        # Display banner the first time run, unless suppressed
        show_banner = True
        try:
            show_banner = settings.get('showBanner')

        except KeyError:
            # disable for subsequent runs
            settings.set(showBanner=False)
            if not os.path.exists(settings.preffile):
                settings.save()

        if (not options.nosplash) and (len(args) == 0) and show_banner:
            ginga_shell.banner(raiseTab=True)

        # Handle inputs like "*.fits[ext]" that sys cmd cannot auto expand.
        expanded_args = []
        for imgfile in args:
            if '*' in imgfile:
                if '[' in imgfile and imgfile.endswith(']'):
                    s = imgfile.split('[')
                    ext = '[' + s[1]
                    imgfile = s[0]
                else:
                    ext = ''
                for fname in glob.iglob(imgfile):
                    expanded_args.append(fname + ext)
            else:
                expanded_args.append(imgfile)

        # Assume remaining arguments are fits files and load them.
        if not options.separate_channels:
            chname = channels[0]
            ginga_shell.gui_do(ginga_shell.open_uris,
                               expanded_args,
                               chname=chname)
        else:
            i = 0
            num_channels = len(channels)
            for imgfile in expanded_args:
                if i < num_channels:
                    chname = channels[i]
                    i = i + 1
                else:
                    channel = ginga_shell.add_channel_auto()
                    chname = channel.name
                ginga_shell.gui_do(ginga_shell.open_uris, [imgfile],
                                   chname=chname)

        try:
            try:
                # if there is a network component, start it
                if hasattr(ginga_shell, 'start'):
                    logger.info("starting network interface...")
                    task = Task.FuncTask2(ginga_shell.start)
                    thread_pool.addTask(task)

                # Main loop to handle GUI events
                logger.info("entering mainloop...")
                ginga_shell.mainloop(timeout=0.001)

            except KeyboardInterrupt:
                logger.error("Received keyboard interrupt!")

        finally:
            logger.info("Shutting down...")
            ev_quit.set()

        sys.exit(0)
Example #30
0
    def find_executable_obs_cb(self, widget):

        self.tree1.clear()
        self.view.update_pending()

        # get a handle to the control panel plugin
        cp = self.view.get_plugin('cp')
        use_db = cp.w.use_qdb.get_state()
        limit_filter = None
        if not self.w.fltr_exch.get_state():
            limit_filter = self.w.filter.get_text().strip()
        cp.update_scheduler(use_db=use_db,
                            limit_filter=limit_filter,
                            allow_delay=self.w.allow_delay.get_state())

        sdlr = self.model.get_scheduler()
        date_s = self.w.date.get_text().strip()
        time_b = self.w.start_time.get_text().strip()

        try:
            time_start = sdlr.site.get_date("%s %s" % (date_s, time_b))
        except Exception as e:
            errmsg = 'Error parsing start date/time:: {}\n'.format(str(e))
            errmsg += "\n".join([e.__class__.__name__, str(e)])
            self.logger.error(errmsg)
            self.view.gui_do(self.view.show_error, errmsg, raisetab=True)
            return

        # find the record in the schedule table that matches our date
        try:
            data = self.get_schedule_data(time_start)
        except ValueError as e:
            errmsg = str(e)
            self.logger.error(errmsg)
            self.view.gui_do(self.view.show_error, errmsg, raisetab=True)
            return

        # should we get the actual installed list of filters instead from
        # Gen2 rather than reading it out of the Schedule
        filters = data.filters
        _filter = self.w.filter.get_text().strip()
        if not _filter in filters:
            errmsg = "filter '{}' not found in available filters: {}".format(
                _filter, str(filters))
            self.logger.error(errmsg)
            self.view.gui_do(self.view.show_error, errmsg, raisetab=True)
            return

        len_s = self.w.len_time.get_text().strip()
        slot_length = max(0.0, float(len_s) * 60.0)

        # override some items from Schedule table
        data.cur_filter = self.w.filter.get_text().strip()
        data.cur_az = float(self.w.az.get_text().strip())
        data.cur_el = float(self.w.el.get_text().strip())
        data.seeing = float(self.w.seeing.get_text().strip())
        data.transparency = float(self.w.trans.get_text().strip())

        slot = entity.Slot(time_start, slot_length, data=data)
        self.slot = slot
        good, bad = sdlr.find_executable_obs(slot)

        tree_dict = OrderedDict()

        # Table header with units
        columns = [('Best', 'index'), ('Program', 'program'),
                   ('OB Code', 'ob_code'), ('Priority', 'priority'),
                   ('Grade', 'grade'), ('Prep', 'prep'), ('On Source', 'time'),
                   ('Target', 'target'), ('Filter', 'filter'),
                   ('Delay', 'delay'), ('Reason', 'reason')]

        self.tree1.setup_table(columns, 1, 'index')

        # This is to get around table widget not sorting numbers properly
        i_fmt = '{{0:0{0}d}}'.format(len(str(len(good))))

        # Table contents
        i = 1
        for rec in good:
            i_str = i_fmt.format(i)
            bnch = Bunch(index=i_str,
                         program=rec.ob.program.proposal,
                         ob_code=rec.ob.name,
                         priority=rec.ob.priority,
                         grade=rec.ob.program.grade,
                         prep="%.2f" % (rec.prep_sec / 60.0),
                         time="%.2f" % (rec.ob.total_time / 60.0),
                         target=rec.ob.target.name,
                         filter=rec.ob.inscfg.filter,
                         delay=rec.delay_sec / 60.0,
                         _group=good,
                         _rec=rec,
                         reason='OK')
            tree_dict[i_str] = bnch
            i += 1

        if self.show_bad:
            for rec in bad:
                i_str = i_fmt.format(i)
                bnch = Bunch(index=i_str,
                             program=rec.ob.program.proposal,
                             ob_code=rec.ob.name,
                             priority=rec.ob.priority,
                             grade=rec.ob.program.grade,
                             prep="%.2f" % (rec.prep_sec / 60.0),
                             time="%.2f" % (rec.ob.total_time / 60.0),
                             target=rec.ob.target.name,
                             filter=rec.ob.inscfg.filter,
                             delay=rec.delay_sec / 60.0,
                             _group=bad,
                             _rec=rec,
                             reason='NG: ' + rec.reason)
                tree_dict[i_str] = bnch
                i += 1

        self.tree1.set_tree(tree_dict)

        self.tree1.set_optimal_column_widths()