예제 #1
0
파일: Mosaic.py 프로젝트: godber/ginga
    def build_gui(self, container):
        top = Widgets.VBox()
        top.set_border_width(4)

        vbox, sw, orientation = Widgets.get_oriented_box(container)
        vbox.set_border_width(4)
        vbox.set_spacing(2)

        self.msgFont = self.fv.getFont("sansFont", 12)
        tw = Widgets.TextArea(wrap=True, editable=False)
        tw.set_font(self.msgFont)
        self.tw = tw

        fr = Widgets.Frame("Instructions")
        vbox2 = Widgets.VBox()
        vbox2.add_widget(tw)
        vbox2.add_widget(Widgets.Label(''), stretch=1)
        fr.set_widget(vbox2)
        vbox.add_widget(fr, stretch=0)
        
        fr = Widgets.Frame("Mosaic")

        captions = [
            ("FOV (deg):", 'label', 'Fov', 'llabel', 'set_fov', 'entry'),
            ("New Mosaic", 'button'),
            ("Label images", 'checkbutton', "Match bg", 'checkbutton'),
            ("Trim Pixels:", 'label', 'Trim Px', 'llabel',
             'trim_pixels', 'entry'),
            ("Num Threads:", 'label', 'Num Threads', 'llabel',
             'set_num_threads', 'entry'),
            ("Merge data", 'checkbutton', "Drop new",
             'checkbutton'),
            ("Mosaic HDUs", 'checkbutton'),
            ]
        w, b = Widgets.build_info(captions, orientation=orientation)
        self.w.update(b)

        fov_deg = self.settings.get('fov_deg', 1.0)
        b.fov.set_text(str(fov_deg))
        b.set_fov.set_length(8)
        b.set_fov.set_text(str(fov_deg))
        b.set_fov.add_callback('activated', self.set_fov_cb)
        b.set_fov.set_tooltip("Set size of mosaic FOV (deg)")
        b.new_mosaic.add_callback('activated', lambda w: self.new_mosaic_cb())
        labelem = self.settings.get('annotate_images', False)
        b.label_images.set_state(labelem)
        b.label_images.set_tooltip("Label tiles with their names")
        b.label_images.add_callback('activated', self.annotate_cb)

        trim_px = self.settings.get('trim_px', 0)
        match_bg = self.settings.get('match_bg', False)
        b.match_bg.set_tooltip("Try to match background levels")
        b.match_bg.set_state(match_bg)
        b.match_bg.add_callback('activated', self.match_bg_cb)
        b.trim_pixels.set_tooltip("Set number of pixels to trim from each edge")
        b.trim_px.set_text(str(trim_px))
        b.trim_pixels.add_callback('activated', self.trim_pixels_cb)
        b.trim_pixels.set_length(8)
        b.trim_pixels.set_text(str(trim_px))

        num_threads = self.settings.get('num_threads', 4)
        b.num_threads.set_text(str(num_threads))
        b.set_num_threads.set_length(8)
        b.set_num_threads.set_text(str(num_threads))
        b.set_num_threads.set_tooltip("Number of threads to use for mosaicing")
        b.set_num_threads.add_callback('activated', self.set_num_threads_cb)
        merge = self.settings.get('merge', False)
        b.merge_data.set_tooltip("Merge data instead of overlay")
        b.merge_data.set_state(merge)
        b.merge_data.add_callback('activated', self.merge_cb)
        drop_new = self.settings.get('drop_creates_new_mosaic', False)
        b.drop_new.set_tooltip("Dropping files on image starts a new mosaic")
        b.drop_new.set_state(drop_new)
        b.drop_new.add_callback('activated', self.drop_new_cb)
        mosaic_hdus = self.settings.get('mosaic_hdus', False)
        b.mosaic_hdus.set_tooltip("Mosaic data HDUs in each file")
        b.mosaic_hdus.set_state(mosaic_hdus)
        b.mosaic_hdus.add_callback('activated', self.mosaic_hdus_cb)

        fr.set_widget(w)
        vbox.add_widget(fr, stretch=0)

        vbox2 = Widgets.VBox()
        # Mosaic evaluation status
        hbox = Widgets.HBox()
        hbox.set_spacing(4)
        hbox.set_border_width(4)
        label = Widgets.Label()
        self.w.eval_status = label
        hbox.add_widget(self.w.eval_status, stretch=0)
        hbox.add_widget(Widgets.Label(''), stretch=1)                
        vbox2.add_widget(hbox, stretch=0)

        # Mosaic evaluation progress bar and stop button
        hbox = Widgets.HBox()
        hbox.set_spacing(4)
        hbox.set_border_width(4)
        btn = Widgets.Button("Stop")
        btn.add_callback('activated', lambda w: self.eval_intr())
        btn.set_enabled(False)
        self.w.btn_intr_eval = btn
        hbox.add_widget(btn, stretch=0)

        self.w.eval_pgs = Widgets.ProgressBar()
        hbox.add_widget(self.w.eval_pgs, stretch=1)

        vbox2.add_widget(hbox, stretch=0)
        vbox2.add_widget(Widgets.Label(''), stretch=1)
        vbox.add_widget(vbox2, stretch=1)

        self.w.vbox = Widgets.VBox()
        vbox.add_widget(self.w.vbox, stretch=0)
        
        spacer = Widgets.Label('')
        vbox.add_widget(spacer, stretch=1)

        top.add_widget(sw, stretch=1)
        
        btns = Widgets.HBox()
        btns.set_spacing(3)

        btn = Widgets.Button("Close")
        btn.add_callback('activated', lambda w: self.close())
        btns.add_widget(btn, stretch=0)
        btns.add_widget(Widgets.Label(''), stretch=1)
        top.add_widget(btns, stretch=0)

        container.add_widget(top, stretch=1)
        self.gui_up = True
예제 #2
0
    def build_gui(self, container):
        assert iqcalc.have_scipy == True, \
               Exception("Please install python-scipy to use this plugin")

        self.pickcenter = None

        vtop = Widgets.VBox()
        vtop.set_border_width(4)

        vbox, sw, orientation = Widgets.get_oriented_box(container)
        vbox.set_border_width(4)
        vbox.set_spacing(2)

        vpaned = Widgets.Splitter(orientation=orientation)

        nb = Widgets.TabWidget(tabpos='bottom')
        #nb.set_scrollable(True)
        self.w.nb1 = nb
        vpaned.add_widget(nb)

        cm, im = self.fv.cm, self.fv.im

        di = CanvasTypes.ImageViewCanvas(logger=self.logger)
        width, height = 200, 200
        di.set_desired_size(width, height)
        di.enable_autozoom('off')
        di.enable_autocuts('off')
        di.zoom_to(3, redraw=False)
        settings = di.get_settings()
        settings.getSetting('zoomlevel').add_callback('set', self.zoomset, di)
        di.set_cmap(cm, redraw=False)
        di.set_imap(im, redraw=False)
        di.set_callback('none-move', self.detailxy)
        di.set_bg(0.4, 0.4, 0.4)
        # for debugging
        di.set_name('pickimage')
        self.pickimage = di

        bd = di.get_bindings()
        bd.enable_pan(True)
        bd.enable_zoom(True)
        bd.enable_cuts(True)

        iw = Widgets.wrap(di.get_widget())
        nb.add_widget(iw, title="Image")

        if have_mpl:
            self.plot1 = Plot.Plot(logger=self.logger,
                                   width=2,
                                   height=3,
                                   dpi=72)
            self.w.canvas = self.plot1.canvas
            self.w.fig = self.plot1.fig
            self.w.ax = self.w.fig.add_subplot(111, axisbg='black')
            self.w.ax.set_aspect('equal', adjustable='box')
            self.w.ax.set_title('Contours')
            #self.w.ax.grid(True)

            canvas = self.w.canvas
            connect = canvas.mpl_connect
            # These are not ready for prime time...
            # connect("motion_notify_event", self.plot_motion_notify)
            # connect("button_press_event", self.plot_button_press)
            connect("scroll_event", self.plot_scroll)
            nb.add_widget(Widgets.wrap(canvas), title="Contour")

            self.plot2 = Plot.Plot(logger=self.logger,
                                   width=2,
                                   height=3,
                                   dpi=72)
            self.w.canvas2 = self.plot2.canvas
            self.w.fig2 = self.plot2.fig
            self.w.ax2 = self.w.fig2.add_subplot(111, axisbg='white')
            #self.w.ax2.set_aspect('equal', adjustable='box')
            self.w.ax2.set_ylabel('brightness')
            self.w.ax2.set_xlabel('pixels')
            self.w.ax2.set_title('FWHM')
            self.w.ax.grid(True)
            canvas = self.w.canvas2
            nb.add_widget(Widgets.wrap(canvas), title="FWHM")

        ## self.msgFont = self.fv.getFont("sansFont", 12)
        ## tw = Widgets.TextArea(wrap=True, editable=False)
        ## tw.set_font(self.msgFont)
        ## self.tw = tw

        ## fr = Widgets.Frame("Instructions")
        ## vbox2 = Widgets.VBox()
        ## vbox2.add_widget(tw)
        ## vbox2.add_widget(Widgets.Label(''), stretch=1)
        ## fr.set_widget(vbox2)
        ## vbox.add_widget(fr, stretch=0)

        vpaned.add_widget(Widgets.Label(''))
        vbox.add_widget(vpaned, stretch=1)

        fr = Widgets.Frame("Pick")

        nb = Widgets.TabWidget(tabpos='bottom')
        self.w.nb2 = nb

        # Build report panel
        captions = (
            ('Zoom:', 'label', 'Zoom', 'llabel', 'Contour Zoom:', 'label',
             'Contour Zoom', 'llabel'),
            ('Object_X', 'label', 'Object_X', 'llabel', 'Object_Y', 'label',
             'Object_Y', 'llabel'),
            ('RA:', 'label', 'RA', 'llabel', 'DEC:', 'label', 'DEC', 'llabel'),
            ('Equinox:', 'label', 'Equinox', 'llabel', 'Background:', 'label',
             'Background', 'llabel'),
            ('Sky Level:', 'label', 'Sky Level', 'llabel', 'Brightness:',
             'label', 'Brightness', 'llabel'),
            ('FWHM X:', 'label', 'FWHM X', 'llabel', 'FWHM Y:', 'label',
             'FWHM Y', 'llabel'),
            ('FWHM:', 'label', 'FWHM', 'llabel', 'Star Size:', 'label',
             'Star Size', 'llabel'),
            ('Sample Area:', 'label', 'Sample Area', 'llabel',
             'Default Region', 'button'),
        )

        w, b = Widgets.build_info(captions, orientation=orientation)
        self.w.update(b)
        b.zoom.set_text(self.fv.scale2text(di.get_scale()))
        self.wdetail = b
        b.default_region.add_callback('activated',
                                      lambda w: self.reset_region())
        b.default_region.set_tooltip("Reset region size to default")

        vbox1 = Widgets.VBox()
        vbox1.add_widget(w, stretch=0)

        # spacer
        vbox1.add_widget(Widgets.Label(''), stretch=0)

        # Pick field evaluation status
        hbox = Widgets.HBox()
        hbox.set_spacing(4)
        hbox.set_border_width(4)
        label = Widgets.Label()
        #label.set_alignment(0.05, 0.5)
        self.w.eval_status = label
        hbox.add_widget(self.w.eval_status, stretch=0)
        hbox.add_widget(Widgets.Label(''), stretch=1)
        vbox1.add_widget(hbox, stretch=0)

        # Pick field evaluation progress bar and stop button
        hbox = Widgets.HBox()
        hbox.set_spacing(4)
        hbox.set_border_width(4)
        btn = Widgets.Button("Stop")
        btn.add_callback('activated', lambda w: self.eval_intr())
        btn.set_enabled(False)
        self.w.btn_intr_eval = btn
        hbox.add_widget(btn, stretch=0)

        self.w.eval_pgs = Widgets.ProgressBar()
        hbox.add_widget(self.w.eval_pgs, stretch=1)
        vbox1.add_widget(hbox, stretch=0)

        nb.add_widget(vbox1, title="Readout")

        # Build settings panel
        captions = (
            ('Show Candidates', 'checkbutton'),
            ('Radius:', 'label', 'xlbl_radius', 'label', 'Radius',
             'spinbutton'),
            ('Threshold:', 'label', 'xlbl_threshold', 'label', 'Threshold',
             'entry'),
            ('Min FWHM:', 'label', 'xlbl_min_fwhm', 'label', 'Min FWHM',
             'spinbutton'),
            ('Max FWHM:', 'label', 'xlbl_max_fwhm', 'label', 'Max FWHM',
             'spinbutton'),
            ('Ellipticity:', 'label', 'xlbl_ellipticity', 'label',
             'Ellipticity', 'entry'),
            ('Edge:', 'label', 'xlbl_edge', 'label', 'Edge', 'entry'),
            ('Max side:', 'label', 'xlbl_max_side', 'label', 'Max side',
             'spinbutton'),
            ('Redo Pick', 'button'),
        )

        w, b = Widgets.build_info(captions, orientation=orientation)
        self.w.update(b)
        b.radius.set_tooltip("Radius for peak detection")
        b.threshold.set_tooltip("Threshold for peak detection (blank=default)")
        b.min_fwhm.set_tooltip("Minimum FWHM for selection")
        b.max_fwhm.set_tooltip("Maximum FWHM for selection")
        b.ellipticity.set_tooltip("Minimum ellipticity for selection")
        b.edge.set_tooltip("Minimum edge distance for selection")
        b.show_candidates.set_tooltip("Show all peak candidates")
        # radius control
        #b.radius.set_digits(2)
        #b.radius.set_numeric(True)
        b.radius.set_limits(5.0, 200.0, incr_value=1.0)
        b.radius.set_value(self.radius)

        def chg_radius(w, val):
            self.radius = float(val)
            self.w.xlbl_radius.set_text(str(self.radius))
            return True

        b.xlbl_radius.set_text(str(self.radius))
        b.radius.add_callback('value-changed', chg_radius)

        # threshold control
        def chg_threshold(w):
            threshold = None
            ths = w.get_text().strip()
            if len(ths) > 0:
                threshold = float(ths)
            self.threshold = threshold
            self.w.xlbl_threshold.set_text(str(self.threshold))
            return True

        b.xlbl_threshold.set_text(str(self.threshold))
        b.threshold.add_callback('activated', chg_threshold)

        # min fwhm
        #b.min_fwhm.set_digits(2)
        #b.min_fwhm.set_numeric(True)
        b.min_fwhm.set_limits(0.1, 200.0, incr_value=0.1)
        b.min_fwhm.set_value(self.min_fwhm)

        def chg_min(w, val):
            self.min_fwhm = float(val)
            self.w.xlbl_min_fwhm.set_text(str(self.min_fwhm))
            return True

        b.xlbl_min_fwhm.set_text(str(self.min_fwhm))
        b.min_fwhm.add_callback('value-changed', chg_min)

        # max fwhm
        #b.max_fwhm.set_digits(2)
        #b.max_fwhm.set_numeric(True)
        b.max_fwhm.set_limits(0.1, 200.0, incr_value=0.1)
        b.max_fwhm.set_value(self.max_fwhm)

        def chg_max(w, val):
            self.max_fwhm = float(val)
            self.w.xlbl_max_fwhm.set_text(str(self.max_fwhm))
            return True

        b.xlbl_max_fwhm.set_text(str(self.max_fwhm))
        b.max_fwhm.add_callback('value-changed', chg_max)

        # Ellipticity control
        def chg_ellipticity(w):
            minellipse = None
            val = w.get_text().strip()
            if len(val) > 0:
                minellipse = float(val)
            self.min_ellipse = minellipse
            self.w.xlbl_ellipticity.set_text(str(self.min_ellipse))
            return True

        b.xlbl_ellipticity.set_text(str(self.min_ellipse))
        b.ellipticity.add_callback('activated', chg_ellipticity)

        # Edge control
        def chg_edgew(w):
            edgew = None
            val = w.get_text().strip()
            if len(val) > 0:
                edgew = float(val)
            self.edgew = edgew
            self.w.xlbl_edge.set_text(str(self.edgew))
            return True

        b.xlbl_edge.set_text(str(self.edgew))
        b.edge.add_callback('activated', chg_edgew)

        #b.max_side.set_digits(0)
        #b.max_side.set_numeric(True)
        b.max_side.set_limits(5, 10000, incr_value=10)
        b.max_side.set_value(self.max_side)

        def chg_max_side(w, val):
            self.max_side = int(val)
            self.w.xlbl_max_side.set_text(str(self.max_side))
            return True

        b.xlbl_max_side.set_text(str(self.max_side))
        b.max_side.add_callback('value-changed', chg_max_side)

        b.redo_pick.add_callback('activated', lambda w: self.redo())
        b.show_candidates.set_state(self.show_candidates)
        b.show_candidates.add_callback('activated', self.show_candidates_cb)

        nb.add_widget(w, title="Settings")

        # Build controls panel
        captions = (
            ('Sky cut', 'button', 'Delta sky:', 'label', 'xlbl_delta_sky',
             'label', 'Delta sky', 'entry'),
            ('Bright cut', 'button', 'Delta bright:', 'label',
             'xlbl_delta_bright', 'label', 'Delta bright', 'entry'),
        )

        w, b = Widgets.build_info(captions, orientation=orientation)
        self.w.update(b)
        b.sky_cut.set_tooltip("Set image low cut to Sky Level")
        b.delta_sky.set_tooltip("Delta to apply to low cut")
        b.bright_cut.set_tooltip("Set image high cut to Sky Level+Brightness")
        b.delta_bright.set_tooltip("Delta to apply to high cut")

        b.sky_cut.set_enabled(False)
        self.w.btn_sky_cut = b.sky_cut
        self.w.btn_sky_cut.add_callback('activated', lambda w: self.sky_cut())
        self.w.sky_cut_delta = b.delta_sky
        b.xlbl_delta_sky.set_text(str(self.delta_sky))
        b.delta_sky.set_text(str(self.delta_sky))

        def chg_delta_sky(w):
            delta_sky = 0.0
            val = w.get_text().strip()
            if len(val) > 0:
                delta_sky = float(val)
            self.delta_sky = delta_sky
            self.w.xlbl_delta_sky.set_text(str(self.delta_sky))
            return True

        b.delta_sky.add_callback('activated', chg_delta_sky)

        b.bright_cut.set_enabled(False)
        self.w.btn_bright_cut = b.bright_cut
        self.w.btn_bright_cut.add_callback('activated',
                                           lambda w: self.bright_cut())
        self.w.bright_cut_delta = b.delta_bright
        b.xlbl_delta_bright.set_text(str(self.delta_bright))
        b.delta_bright.set_text(str(self.delta_bright))

        def chg_delta_bright(w):
            delta_bright = 0.0
            val = w.get_text().strip()
            if len(val) > 0:
                delta_bright = float(val)
            self.delta_bright = delta_bright
            self.w.xlbl_delta_bright.set_text(str(self.delta_bright))
            return True

        b.delta_bright.add_callback('activated', chg_delta_bright)

        nb.add_widget(w, title="Controls")

        vbox3 = Widgets.VBox()
        msgFont = self.fv.getFont("fixedFont", 10)
        tw = Widgets.TextArea(wrap=False, editable=True)
        tw.set_font(msgFont)
        self.w.report = tw
        sw1 = Widgets.ScrollArea()
        sw1.set_widget(tw)
        vbox3.add_widget(sw1, stretch=1)
        tw.append_text(self._mkreport_header())

        btns = Widgets.HBox()
        btns.set_spacing(4)

        btn = Widgets.Button("Add Pick")
        btn.add_callback('activated', lambda w: self.add_pick_cb())
        btns.add_widget(btn)
        btn = Widgets.CheckBox("Record Picks")
        btn.set_state(self.do_record)
        btn.add_callback('activated', self.record_cb)
        btns.add_widget(btn)
        btns.add_widget(Widgets.Label(''), stretch=1)
        vbox3.add_widget(btns, stretch=0)

        nb.add_widget(vbox3, title="Report")

        ## vbox4 = Widgets.VBox()
        ## tw = Widgets.TextArea(wrap=False, editable=True)
        ## tw.set_font(msgFont)
        ## self.w.correct = tw
        ## sw1 = Widgets.ScrollArea()
        ## sw1.set_widget(tw)
        ## vbox4.add_widget(sw1, stretch=1)
        ## tw.append_text("# paste a reference report here")

        ## btns = Widgets.HBox()
        ## btns.set_spacing(4)

        ## btn = Widgets.Button("Correct WCS")
        ## btn.add_callback('activated', lambda w: self.correct_wcs())
        ## btns.add_widget(btn)
        ## vbox4.add_widget(btns, stretch=0)

        ## nb.add_widget(vbox4, title="Correct")

        fr.set_widget(nb)
        vbox.add_widget(fr, stretch=0)

        ## spacer = Widgets.Label('')
        ## vbox.add_widget(spacer, stretch=1)

        vtop.add_widget(sw, stretch=1)

        btns = Widgets.HBox()
        btns.set_spacing(4)

        btn = Widgets.Button("Close")
        btn.add_callback('activated', lambda w: self.close())
        btns.add_widget(btn)
        btns.add_widget(Widgets.Label(''), stretch=1)
        vtop.add_widget(btns, stretch=0)

        container.add_widget(vtop, stretch=1)
예제 #3
0
    def build_gui(self, container):
        top = Widgets.VBox()
        top.set_border_width(4)

        vbox1, sw, orientation = Widgets.get_oriented_box(container)
        vbox1.set_border_width(4)
        vbox1.set_spacing(2)

        self.msgFont = self.fv.getFont("sansFont", 12)
        tw = Widgets.TextArea(wrap=True, editable=False)
        tw.set_font(self.msgFont)
        self.tw = tw

        fr = Widgets.Frame("Instructions")
        vbox2 = Widgets.VBox()
        vbox2.add_widget(tw)
        vbox2.add_widget(Widgets.Label(''), stretch=1)
        fr.set_widget(vbox2)
        vbox1.add_widget(fr, stretch=0)
        
        # Main pipeline control area
        captions = [
            ("Subtract Bias", 'button', "Bias Image:", 'label',
             'bias_image', 'llabel'),
            ("Apply Flat Field", 'button', "Flat Image:", 'label',
             'flat_image', 'llabel'),
            ]
        w, b = Widgets.build_info(captions, orientation=orientation)
        self.w.update(b)

        fr = Widgets.Frame("Pipeline")
        fr.set_widget(w)
        vbox1.add_widget(fr, stretch=0)

        b.subtract_bias.add_callback('activated', self.subtract_bias_cb)
        b.subtract_bias.set_tooltip("Subtract a bias image")
        bias_name = 'None'
        if self.bias != None:
            bias_name = self.bias.get('name', "NoName")
        b.bias_image.set_text(bias_name)

        b.apply_flat_field.add_callback('activated', self.apply_flat_cb)
        b.apply_flat_field.set_tooltip("Apply a flat field correction")
        flat_name = 'None'
        if self.flat != None:
            flat_name = self.flat.get('name', "NoName")
        b.flat_image.set_text(flat_name)

        vbox2 = Widgets.VBox()
        # Pipeline status
        hbox = Widgets.HBox()
        hbox.set_spacing(4)
        hbox.set_border_width(4)
        label = Widgets.Label()
        self.w.eval_status = label
        hbox.add_widget(self.w.eval_status, stretch=0)
        hbox.add_widget(Widgets.Label(''), stretch=1)                
        vbox2.add_widget(hbox, stretch=0)

        # progress bar and stop button
        hbox = Widgets.HBox()
        hbox.set_spacing(4)
        hbox.set_border_width(4)
        btn = Widgets.Button("Stop")
        btn.add_callback('activated', lambda w: self.eval_intr())
        btn.set_enabled(False)
        self.w.btn_intr_eval = btn
        hbox.add_widget(btn, stretch=0)

        self.w.eval_pgs = Widgets.ProgressBar()
        hbox.add_widget(self.w.eval_pgs, stretch=1)
        vbox2.add_widget(hbox, stretch=0)
        vbox2.add_widget(Widgets.Label(''), stretch=1)
        vbox1.add_widget(vbox2, stretch=0)

        # Image list 
        captions = [
            ("Append", 'button', "Prepend", 'button', "Clear", 'button'),
            ]
        w, b = Widgets.build_info(captions, orientation=orientation)
        self.w.update(b)

        fr = Widgets.Frame("Image Stack")

        vbox = Widgets.VBox()
        hbox = Widgets.HBox()
        self.w.stack = Widgets.Label('')
        hbox.add_widget(self.w.stack, stretch=0)
        vbox.add_widget(hbox, stretch=0)
        vbox.add_widget(w, stretch=0)
        fr.set_widget(vbox)
        vbox1.add_widget(fr, stretch=0)

        self.update_stack_gui()
        
        b.append.add_callback('activated', self.append_image_cb)
        b.append.set_tooltip("Append an individual image to the stack")
        b.prepend.add_callback('activated', self.prepend_image_cb)
        b.prepend.set_tooltip("Prepend an individual image to the stack")
        b.clear.add_callback('activated', self.clear_stack_cb)
        b.clear.set_tooltip("Clear the stack of images")

        # Bias
        captions = [
            ("Make Bias", 'button', "Set Bias", 'button'),
            ]
        w, b = Widgets.build_info(captions, orientation=orientation)
        self.w.update(b)

        fr = Widgets.Frame("Bias Subtraction")
        fr.set_widget(w)
        vbox1.add_widget(fr, stretch=0)

        b.make_bias.add_callback('activated', self.make_bias_cb)
        b.make_bias.set_tooltip("Makes a bias image from a stack of individual images")
        b.set_bias.add_callback('activated', self.set_bias_cb)
        b.set_bias.set_tooltip("Set the currently loaded image as the bias image")

        # Flat fielding
        captions = [
            ("Make Flat Field", 'button', "Set Flat Field", 'button'),
            ]
        w, b = Widgets.build_info(captions, orientation=orientation)
        self.w.update(b)

        fr = Widgets.Frame("Flat Fielding")
        fr.set_widget(w)
        vbox1.add_widget(fr, stretch=0)

        b.make_flat_field.add_callback('activated', self.make_flat_cb)
        b.make_flat_field.set_tooltip("Makes a flat field from a stack of individual flats")
        b.set_flat_field.add_callback('activated', self.set_flat_cb)
        b.set_flat_field.set_tooltip("Set the currently loaded image as the flat field")

        spacer = Widgets.Label('')
        vbox1.add_widget(spacer, stretch=1)
        
        top.add_widget(sw, stretch=1)
        
        btns = Widgets.HBox()
        btns.set_spacing(3)

        btn = Widgets.Button("Close")
        btn.add_callback('activated', lambda w: self.close())
        btns.add_widget(btn, stretch=0)
        btns.add_widget(Widgets.Label(''), stretch=1)
        top.add_widget(btns, stretch=0)

        container.add_widget(top, stretch=1)
        self.gui_up = True