Beispiel #1
0
 def fastReplot(self, *dum):
     """Fast replot -- called when flipping images or slices. Uses the plot cache, if possible."""
     if self._plot:
         self.resetDrawKey()
         dprint(2, "calling replot", time.time() % 60)
         self._plot.replot()
         dprint(2, "replot done", time.time() % 60)
Beispiel #2
0
 def _createImageController(self, image, name, basename, model=False, save=False):
     dprint(2, "creating ImageController for", name)
     ic = ImageController(image, self, self, name, save=save)
     ic.setNumber(len(self._imagecons))
     self._imagecons.insert(0, ic)
     self._imagecon_loadorder.append(ic)
     if model:
         self._model_imagecons.add(id(ic))
     self._lo.addWidget(ic)
     if self._border_pen:
         ic.addPlotBorder(self._border_pen, basename, self._label_color, self._label_bg_brush)
     # attach appropriate signals
     image.connect(SIGNAL("slice"), self.fastReplot)
     image.connect(SIGNAL("repaint"), self.replot)
     image.connect(SIGNAL("raise"), self._currier.curry(self.raiseImage, ic))
     image.connect(SIGNAL("unload"), self._currier.curry(self.unloadImage, ic))
     image.connect(SIGNAL("center"), self._currier.curry(self.centerImage, ic))
     QObject.connect(ic.renderControl(), SIGNAL("displayRangeChanged"),
                     self._currier.curry(self._updateDisplayRange, ic.renderControl()))
     QObject.connect(ic.renderControl(), SIGNAL("displayRangeLocked"),
                     self._currier.curry(self._lockDisplayRange, ic.renderControl()))
     self._plot = None
     # add to menus
     dprint(2, "repopulating menus")
     self._repopulateMenu()
     # center and raise to top of stack
     self.raiseImage(ic)
     if not self._center_image:
         self.centerImage(ic, emit=False)
     else:
         ic.setPlotProjection(self._center_image.projection)
     # signal
     self.emit(SIGNAL("imagesChanged"))
     return ic
Beispiel #3
0
 def fastReplot(self, *dum):
     """Fast replot -- called when flipping images or slices. Uses the plot cache, if possible."""
     if self._plot:
         self.resetDrawKey()
         dprint(2, "calling replot", time.time() % 60)
         self._plot.replot()
         dprint(2, "replot done", time.time() % 60)
Beispiel #4
0
 def loadImage(self, filename=None, duplicate=True, to_top=True, model=None):
     """Loads image. Returns ImageControlBar object.
     If image is already loaded: returns old ICB if duplicate=False (raises to top if to_top=True),
     or else makes a new control bar.
     If model is set to a source name, marks the image as associated with a model source. These can be unloaded en masse by calling
     unloadModelImages().
     """
     if filename is None:
         if not self._load_image_dialog:
             dialog = self._load_image_dialog = QFileDialog(self, "Load FITS image", ".",
                                                            "FITS images (%s);;All files (*)" % (" ".join(
                                                                ["*" + ext for ext in FITS_ExtensionList])))
             dialog.setFileMode(QFileDialog.ExistingFile)
             dialog.setModal(True)
             QObject.connect(dialog, SIGNAL("filesSelected(const QStringList &)"), self.loadImage)
         self._load_image_dialog.exec_()
         return None
     if isinstance(filename, QStringList):
         filename = filename[0]
     filename = str(filename)
     # report error if image does not exist
     if not os.path.exists(filename):
         self.showErrorMessage("""FITS image %s does not exist.""" % filename)
         return None
     # see if image is already loaded
     if not duplicate:
         for ic in self._imagecons:
             if ic.getFilename() and os.path.samefile(filename, ic.getFilename()):
                 if to_top:
                     self.raiseImage(ic)
                 if model:
                     self._model_imagecons.add(id(ic))
                 return ic
     # load the FITS image
     busy = BusyIndicator()
     dprint(2, "reading FITS image", filename)
     self.showMessage("""Reading FITS image %s""" % filename, 3000)
     QApplication.flush()
     try:
         image = SkyImage.FITSImagePlotItem(str(filename))
     except KeyboardInterrupt:
         raise
     except:
         busy = None
         traceback.print_exc()
         self.showErrorMessage("""<P>Error loading FITS image %s: %s. This may be due to a bug in Tigger; if the FITS file loads fine in another viewer,
       please send the FITS file, along with a copy of any error messages from the text console, to [email protected].</P>""" % (
         filename, str(sys.exc_info()[1])))
         return None
     # create control bar, add to widget stack
     ic = self._createImageController(image, "model source '%s'" % model if model else filename, model or image.name,
                                      model=model)
     self.showMessage("""Loaded FITS image %s""" % filename, 3000)
     dprint(2, "image loaded")
     return ic
Beispiel #5
0
 def _createImageController(self,
                            image,
                            name,
                            basename,
                            model=False,
                            save=False):
     dprint(2, "creating ImageController for", name)
     ic = ImageController(image, self, self, name, save=save)
     ic.setNumber(len(self._imagecons))
     self._imagecons.insert(0, ic)
     self._imagecon_loadorder.append(ic)
     if model:
         self._model_imagecons.add(id(ic))
     self._lo.addWidget(ic)
     if self._border_pen:
         ic.addPlotBorder(self._border_pen, basename, self._label_color,
                          self._label_bg_brush)
     # attach appropriate signals
     image.connect(SIGNAL("slice"), self.fastReplot)
     image.connect(SIGNAL("repaint"), self.replot)
     image.connect(SIGNAL("raise"),
                   self._currier.curry(self.raiseImage, ic))
     image.connect(SIGNAL("unload"),
                   self._currier.curry(self.unloadImage, ic))
     image.connect(SIGNAL("center"),
                   self._currier.curry(self.centerImage, ic))
     QObject.connect(
         ic.renderControl(), SIGNAL("displayRangeChanged"),
         self._currier.curry(self._updateDisplayRange, ic.renderControl()))
     QObject.connect(
         ic.renderControl(), SIGNAL("displayRangeLocked"),
         self._currier.curry(self._lockDisplayRange, ic.renderControl()))
     self._plot = None
     # add to menus
     dprint(2, "repopulating menus")
     self._repopulateMenu()
     # center and raise to top of stack
     self.raiseImage(ic)
     if not self._center_image:
         self.centerImage(ic, emit=False)
     else:
         ic.setPlotProjection(self._center_image.projection)
     # signal
     self.emit(SIGNAL("imagesChanged"))
     return ic
Beispiel #6
0
 def close(self):
     dprint(1, "closing Manager")
     self._closing = True
     for ic in self._imagecons:
         ic.close()
Beispiel #7
0
    def computeImage(self, expression=None):
        """Computes image from expression (if expression is None, pops up dialog)"""
        if expression is None:
            (expression, ok) = QInputDialog.getText(self, "Compute image",
                                                    """Enter an image expression to compute.
                                              Any valid numpy expression is supported, and
                                              all functions from the numpy module are available (including sub-modules such as fft).
                                              Use 'a', 'b', 'c' to refer to images.
                                              Examples:  "(a+b)/2", "cos(a)+sin(b)", "a-a.mean()", "fft.fft2(a)", etc.""")
            #      (expression,ok) = QInputDialog.getText(self,"Compute image","""<P>Enter an expression to compute.
            #        Use 'a', 'b', etc. to refer to loaded images. Any valid numpy expression is supported, and all the
            #       functions from the numpy module are available. Examples of valid expressions include "(a+b)/2",
            #       "cos(a)+sin(b)", "a-a.mean()", etc.
            #        </P>
            #      """)
            expression = str(expression)
            if not ok or not expression:
                return
        # try to parse expression
        arglist = [(chr(ord('a') + ic.getNumber()), ic.image) for ic in self._imagecons]
        try:
            exprfunc = eval("lambda " + (",".join([x[0] for x in arglist])) + ":" + expression,
                            numpy.__dict__, {})
        except Exception as exc:
            self.showErrorMessage("""Error parsing expression "%s": %s.""" % (expression, str(exc)))
            return None
        # try to evaluate expression
        self.showMessage("Computing expression \"%s\"" % expression, 10000)
        busy = BusyIndicator()
        QApplication.flush()

        # trim trivial trailing dimensions. This avoids the problem of when an NxMx1 and an NxMx1x1 arrays are added,
        # the result is promoted to NxMxMx1 following the numpy rules.
        def trimshape(shape):
            out = shape
            while out and out[-1] == 1:
                out = out[:-1]
            return out

        def trimarray(array):
            return array.reshape(trimshape(array.shape))

        try:
            result = exprfunc(*[trimarray(x[1].data()) for x in arglist])
        except Exception as exc:
            busy = None
            traceback.print_exc()
            self.showErrorMessage("""Error evaluating "%s": %s.""" % (expression, str(exc)))
            return None
        busy = None
        if type(result) != numpy.ma.masked_array and type(result) != numpy.ndarray:
            self.showErrorMessage(
                """Result of "%s" is of invalid type "%s" (array expected).""" % (expression, type(result).__name__))
            return None
        # convert coomplex results to real
        if numpy.iscomplexobj(result):
            self.showErrorMessage("""Result of "%s" is complex. Complex images are currently
      not fully supported, so we'll implicitly use the absolute value instead.""" % (expression))
            expression = "abs(%s)" % expression
            result = abs(result)
        # determine which image this expression can be associated with
        res_shape = trimshape(result.shape)
        arglist = [x for x in arglist if hasattr(x[1], 'fits_header') and trimshape(x[1].data().shape) == res_shape]
        if not arglist:
            self.showErrorMessage("""Result of "%s" has shape %s, which does not match any loaded FITS image.""" % (
            expression, "x".join(map(str, result.shape))))
            return None
        # look for an image in the arglist with the same projection, and with a valid dirname
        # (for the where-to-save hint)
        template = arglist[0][1]
        # if all images in arglist have the same projection, then it doesn't matter what we use
        # else ask
        if len([x for x in arglist[1:] if x[1].projection == template.projection]) != len(arglist) - 1:
            options = [x[0] for x in arglist]
            (which, ok) = QInputDialog.getItem(self, "Compute image",
                                               "Coordinate system to use for the result of \"%s\":" % expression,
                                               options, 0, False)
            if not ok:
                return None
            try:
                template = arglist[options.index(which)][1]
            except:
                pass
        # create a FITS image
        busy = BusyIndicator()
        dprint(2, "creating FITS image", expression)
        self.showMessage("""Creating image for %s""" % expression, 3000)
        QApplication.flush()
        try:
            hdu = pyfits.PrimaryHDU(result.transpose(), template.fits_header)
            skyimage = SkyImage.FITSImagePlotItem(name=expression, filename=None, hdu=hdu)
        except:
            busy = None
            traceback.print_exc()
            self.showErrorMessage("""Error creating FITS image %s: %s""" % (expression, str(sys.exc_info()[1])))
            return None
        # get directory name for save-to hint
        dirname = getattr(template, 'filename', None)
        if not dirname:
            dirnames = [getattr(img, 'filename') for x, img in arglist if hasattr(img, 'filename')]
            dirname = dirnames[0] if dirnames else None
        # create control bar, add to widget stack
        self._createImageController(skyimage, expression, expression,
                                    save=((dirname and os.path.dirname(dirname)) or "."))
        self.showMessage("Created new image for %s" % expression, 3000)
        dprint(2, "image created")
Beispiel #8
0
 def loadImage(self,
               filename=None,
               duplicate=True,
               to_top=True,
               model=None):
     """Loads image. Returns ImageControlBar object.
     If image is already loaded: returns old ICB if duplicate=False (raises to top if to_top=True),
     or else makes a new control bar.
     If model is set to a source name, marks the image as associated with a model source. These can be unloaded en masse by calling
     unloadModelImages().
     """
     if filename is None:
         if not self._load_image_dialog:
             dialog = self._load_image_dialog = QFileDialog(
                 self, "Load FITS image", ".",
                 "FITS images (%s);;All files (*)" %
                 (" ".join(["*" + ext for ext in FITS_ExtensionList])))
             dialog.setFileMode(QFileDialog.ExistingFile)
             dialog.setModal(True)
             QObject.connect(dialog,
                             SIGNAL("filesSelected(const QStringList &)"),
                             self.loadImage)
         self._load_image_dialog.exec_()
         return None
     if isinstance(filename, QStringList):
         filename = filename[0]
     filename = str(filename)
     # report error if image does not exist
     if not os.path.exists(filename):
         self.showErrorMessage("""FITS image %s does not exist.""" %
                               filename)
         return None
     # see if image is already loaded
     if not duplicate:
         for ic in self._imagecons:
             if ic.getFilename() and os.path.samefile(
                     filename, ic.getFilename()):
                 if to_top:
                     self.raiseImage(ic)
                 if model:
                     self._model_imagecons.add(id(ic))
                 return ic
     # load the FITS image
     busy = BusyIndicator()
     dprint(2, "reading FITS image", filename)
     self.showMessage("""Reading FITS image %s""" % filename, 3000)
     QApplication.flush()
     try:
         image = SkyImage.FITSImagePlotItem(str(filename))
     except KeyboardInterrupt:
         raise
     except:
         busy = None
         traceback.print_exc()
         self.showErrorMessage(
             """<P>Error loading FITS image %s: %s. This may be due to a bug in Tigger; if the FITS file loads fine in another viewer,
       please send the FITS file, along with a copy of any error messages from the text console, to [email protected].</P>"""
             % (filename, str(sys.exc_info()[1])))
         return None
     # create control bar, add to widget stack
     ic = self._createImageController(image,
                                      "model source '%s'" %
                                      model if model else filename,
                                      model or image.name,
                                      model=model)
     self.showMessage("""Loaded FITS image %s""" % filename, 3000)
     dprint(2, "image loaded")
     return ic
Beispiel #9
0
 def close(self):
     dprint(1, "closing Manager")
     self._closing = True
     for ic in self._imagecons:
         ic.close()
Beispiel #10
0
    def computeImage(self, expression=None):
        """Computes image from expression (if expression is None, pops up dialog)"""
        if expression is None:
            (expression, ok) = QInputDialog.getText(
                self, "Compute image", """Enter an image expression to compute.
                                              Any valid numpy expression is supported, and
                                              all functions from the numpy module are available (including sub-modules such as fft).
                                              Use 'a', 'b', 'c' to refer to images.
                                              Examples:  "(a+b)/2", "cos(a)+sin(b)", "a-a.mean()", "fft.fft2(a)", etc."""
            )
            #      (expression,ok) = QInputDialog.getText(self,"Compute image","""<P>Enter an expression to compute.
            #        Use 'a', 'b', etc. to refer to loaded images. Any valid numpy expression is supported, and all the
            #       functions from the numpy module are available. Examples of valid expressions include "(a+b)/2",
            #       "cos(a)+sin(b)", "a-a.mean()", etc.
            #        </P>
            #      """)
            expression = str(expression)
            if not ok or not expression:
                return
        # try to parse expression
        arglist = [(chr(ord('a') + ic.getNumber()), ic.image)
                   for ic in self._imagecons]
        try:
            exprfunc = eval(
                "lambda " + (",".join([x[0]
                                       for x in arglist])) + ":" + expression,
                numpy.__dict__, {})
        except Exception as exc:
            self.showErrorMessage("""Error parsing expression "%s": %s.""" %
                                  (expression, str(exc)))
            return None
        # try to evaluate expression
        self.showMessage("Computing expression \"%s\"" % expression, 10000)
        busy = BusyIndicator()
        QApplication.flush()

        # trim trivial trailing dimensions. This avoids the problem of when an NxMx1 and an NxMx1x1 arrays are added,
        # the result is promoted to NxMxMx1 following the numpy rules.
        def trimshape(shape):
            out = shape
            while out and out[-1] == 1:
                out = out[:-1]
            return out

        def trimarray(array):
            return array.reshape(trimshape(array.shape))

        try:
            result = exprfunc(*[trimarray(x[1].data()) for x in arglist])
        except Exception as exc:
            busy = None
            traceback.print_exc()
            self.showErrorMessage("""Error evaluating "%s": %s.""" %
                                  (expression, str(exc)))
            return None
        busy = None
        if type(result) != numpy.ma.masked_array and type(
                result) != numpy.ndarray:
            self.showErrorMessage(
                """Result of "%s" is of invalid type "%s" (array expected)."""
                % (expression, type(result).__name__))
            return None
        # convert coomplex results to real
        if numpy.iscomplexobj(result):
            self.showErrorMessage(
                """Result of "%s" is complex. Complex images are currently
      not fully supported, so we'll implicitly use the absolute value instead."""
                % (expression))
            expression = "abs(%s)" % expression
            result = abs(result)
        # determine which image this expression can be associated with
        res_shape = trimshape(result.shape)
        arglist = [
            x for x in arglist if hasattr(x[1], 'fits_header')
            and trimshape(x[1].data().shape) == res_shape
        ]
        if not arglist:
            self.showErrorMessage(
                """Result of "%s" has shape %s, which does not match any loaded FITS image."""
                % (expression, "x".join(map(str, result.shape))))
            return None
        # look for an image in the arglist with the same projection, and with a valid dirname
        # (for the where-to-save hint)
        template = arglist[0][1]
        # if all images in arglist have the same projection, then it doesn't matter what we use
        # else ask
        if len(
            [x for x in arglist[1:] if x[1].projection == template.projection
             ]) != len(arglist) - 1:
            options = [x[0] for x in arglist]
            (which, ok) = QInputDialog.getItem(
                self, "Compute image",
                "Coordinate system to use for the result of \"%s\":" %
                expression, options, 0, False)
            if not ok:
                return None
            try:
                template = arglist[options.index(which)][1]
            except:
                pass
        # create a FITS image
        busy = BusyIndicator()
        dprint(2, "creating FITS image", expression)
        self.showMessage("""Creating image for %s""" % expression, 3000)
        QApplication.flush()
        try:
            hdu = pyfits.PrimaryHDU(result.transpose(), template.fits_header)
            skyimage = SkyImage.FITSImagePlotItem(name=expression,
                                                  filename=None,
                                                  hdu=hdu)
        except:
            busy = None
            traceback.print_exc()
            self.showErrorMessage("""Error creating FITS image %s: %s""" %
                                  (expression, str(sys.exc_info()[1])))
            return None
        # get directory name for save-to hint
        dirname = getattr(template, 'filename', None)
        if not dirname:
            dirnames = [
                getattr(img, 'filename') for x, img in arglist
                if hasattr(img, 'filename')
            ]
            dirname = dirnames[0] if dirnames else None
        # create control bar, add to widget stack
        self._createImageController(
            skyimage,
            expression,
            expression,
            save=((dirname and os.path.dirname(dirname)) or "."))
        self.showMessage("Created new image for %s" % expression, 3000)
        dprint(2, "image created")
Beispiel #11
0
 # (for the where-to-save hint)
 template = arglist[0][1];
 # if all images in arglist have the same projection, then it doesn't matter what we use
 # else ask
 if len([x for x in arglist[1:] if x[1].projection == template.projection]) != len(arglist)-1:
   options = [ x[0] for x in arglist ];
   (which,ok) = QInputDialog.getItem(self,"Compute image","Coordinate system to use for the result of \"%s\":"%expression,options,0,False);
   if not ok:
     return None;
   try:
     template = arglist[options.index(which)][1];
   except:
     pass;
 # create a FITS image
 busy = BusyIndicator();
 dprint(2,"creating FITS image",expression);
 self.showMessage("""Creating image for %s"""%expression,3000);
 QApplication.flush();
 try:
   hdu = pyfits.PrimaryHDU(result.transpose(),template.fits_header);
   skyimage = SkyImage.FITSImagePlotItem(name=expression,filename=None,hdu=hdu);
 except:
   busy = None;
   traceback.print_exc();
   self.showErrorMessage("""Error creating FITS image %s: %s"""%(expression,str(sys.exc_info()[1])));
   return None;
 # get directory name for save-to hint
 dirname = getattr(template,'filename',None);
 if not dirname:
   dirnames = [ getattr(img,'filename') for x,img in arglist if hasattr(img,'filename') ];
   dirname = dirnames[0] if dirnames else None;