Esempio n. 1
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
Esempio n. 2
0
 def openFile(self, filename=None, format=None, merge=False, show=True):
     # check that we can close existing model
     if not merge and not self._canCloseExistingModel():
         return False
     if isinstance(filename, QStringList):
         filename = filename[0]
     filename = str(filename)
     # try to determine the file type
     filetype, import_func, export_func, doc = Tigger.Models.Formats.resolveFormat(filename, format)
     if import_func is None:
         self.showErrorMessage("""Error loading model file %s: unknown file format""" % filename)
         return
     # try to load the specified file
     busy = BusyIndicator()
     self.showMessage("""Reading %s file %s""" % (filetype, filename), 3000)
     QApplication.flush()
     try:
         model = import_func(filename)
         model.setFilename(filename)
     except:
         busy = None
         self.showErrorMessage("""Error loading '%s' file %s: %s""" % (filetype, filename, str(sys.exc_info()[1])))
         return
     # set the layout
     if show:
         self.setLayout(self.LayoutImageModel)
     # add to content
     if merge and self.model:
         self.model.addSources(model.sources)
         self.showMessage("""Merged in %d sources from '%s' file %s""" % (len(model.sources), filetype, filename),
                          3000)
         self.model.emitUpdate(SkyModel.UpdateAll)
     else:
         self.showMessage("""Loaded %d sources from '%s' file %s""" % (len(model.sources), filetype, filename),
                          3000)
         self._display_filename = os.path.basename(filename)
         self.setModel(model)
         self._indicateModelUpdated(updated=False)
         # only set self.filename if an export function is available for this format. Otherwise set it to None, so that trying to save
         # the file results in a save-as operation (so that we don't save to a file in an unsupported format).
         self.filename = filename if export_func else None
Esempio n. 3
0
 def _saveImage(self):
     filename = QFileDialog.getSaveFileName(self, "Save FITS file", self._save_dir,
                                            "FITS files(*.fits *.FITS *fts *FTS)")
     filename = str(filename)
     if not filename:
         return
     busy = BusyIndicator()
     self._imgman.showMessage("""Writing FITS image %s""" % filename, 3000)
     QApplication.flush()
     try:
         self.image.save(filename)
     except Exception as exc:
         busy = None
         traceback.print_exc()
         self._imgman.showErrorMessage("""Error writing FITS image %s: %s""" % (filename, str(sys.exc_info()[1])))
         return None
     self.renderControl().startSavingConfig(filename)
     self.setName(self.image.name)
     self._qa_save.setVisible(False)
     self._wsave.hide()
     busy = None
Esempio n. 4
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")
Esempio n. 5
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
Esempio n. 6
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")