Пример #1
0
 def _showMeanStd(self, busy=True):
     if busy:
         busy = BusyIndicator()
     dmin, dmax = self._subset_range
     subset, mask = self.image.optimalRavel(self._subset)
     dprint(5, "computing mean")
     mean = measurements.mean(subset, labels=mask, index=None if mask is None else False)
     dprint(5, "computing std")
     std = measurements.standard_deviation(subset, labels=mask, index=None if mask is None else False)
     dprint(5, "done")
     text = "  ".join([("%s: " + DataValueFormat) % (name, value) for name, value in
                       (("min", dmin), ("max", dmax), ("mean", mean), ("\n std", std))] + ["np: %d" % self._subset.size])
     self._wlab_stats.setText(text)
     self._wmore_stats.hide()
     # update markers
     ypos = 0.3
     self._line_mean.line.setData([mean, mean], [0, 1])
     self._line_mean.marker.setValue(mean, ypos)
     self._line_mean.setText(("\u03BC=" + DataValueFormat) % mean)
     self._line_mean.show()
     self._line_std.line.setData([mean - std, mean + std], [ypos, ypos])
     self._line_std.marker.setValue(mean, ypos)
     self._line_std.setText(("\u03C3=" + DataValueFormat) % std)
     self._line_std.show()
     self._histplot.replot()
     if not isinstance(busy, bool):
         busy.reset_cursor()
Пример #2
0
 def _select_percentile_threshold(self, percent, do_select=False):
     # ignore if no sort index set up, or if _select_threshold() is being called
     if self._sort_index is None or self._in_select_threshold:
         return
     dprint(1, "select_precentile_threshold", percent)
     busy = BusyIndicator()
     # number of objects to select
     nsrc = len(self._sort_index)
     nsel = int(math.ceil(nsrc * float(percent) / 100))
     # get comparison operator
     opstr = str(self.wgele.currentText())
     op, select = self.Operators[opstr]
     # select head or tail of list, depending on direction of operator
     if select:
         thr = self._sort_index[min(nsel, nsrc - 1)]
         slc1 = slice(0, nsel)
         slc2 = slice(nsel, None)
     else:
         thr = self._sort_index[-min(nsel + 1, nsrc)]
         slc1 = slice(nsrc - nsel, None)
         slc2 = slice(0, nsrc - nsel)
     if do_select:
         for val, src, cumsum in self._sort_index[slc1]:
             src.selected = True
         for val, src, cumsum in self._sort_index[slc2]:
             src.selected = False
         self.model.emitSelection(self)
     self.wpercent_lbl.setText("%3d%%" % percent)
     self.wthreshold.setText(
         "%g" % (thr[2] if opstr.startswith("sum") else thr[0]))
     busy.reset_cursor()
     return nsel
Пример #3
0
 def _refreshModel(self, what=SkyModel.UpdateAll, origin=None):
     if origin is self or not what & (SkyModel.UpdateSourceList
                                      | SkyModel.UpdateSourceContent):
         return
     # if only selection was changed, take shortcut
     if what & SkyModel.UpdateSelectionOnly:
         dprint(2, "model update -- selection only")
         return self._refreshSelectedItems(origin)
     busy = BusyIndicator()
     # else repopulate widget completely
     dprint(2, "model update -- complete")
     TigGUI.kitties.widgets.ClickableTreeWidget.clear(self)
     dprint(2, "creating model items")
     items = [SkyModelTreeWidgetItem(src) for src in self.model.sources]
     self._itemdict = dict(
         list(zip([src.name for src in self.model.sources], items)))
     dprint(2, "adding to tree widget")
     self.addTopLevelItems(items)
     self.header().updateGeometry()
     # show/hide columns based on tag availability
     self._enableColumn(ColumnIapp, 'Iapp' in self.model.tagnames)
     self._enableColumn(ColumnR, 'r' in self.model.tagnames)
     dprint(2, "re-sorting")
     self.sortItems(('Iapp' in self.model.tagnames and ColumnIapp)
                    or ColumnI, Qt.DescendingOrder)
     busy.reset_cursor()
Пример #4
0
 def selectSources(self, predicate, curry=False):
     """Selects sources according to predicate(src)"""
     busy = BusyIndicator()
     for src in self.model.sources:
         src.selected = predicate(src)
     self.model.emitSelection(origin=self)
     busy.reset_cursor()
Пример #5
0
 def updateColorMapParameters(self):
     """Call this when the colormap parameters have changed"""
     busy = BusyIndicator()
     self.image.updateCurrentColorMap()
     if self._config:
         self._cmap_list[self._current_cmap_index].saveConfig(self._config)
     busy.reset_cursor()
Пример #6
0
 def _unselectAll(self):
     if not self.model:
         return
     busy = BusyIndicator()
     for src in self.model.sources:
         src.selected = False
     self.model.emitSelection(self)
     busy.reset_cursor()
Пример #7
0
 def _selectInvert(self):
     if not self.model:
         return
     busy = BusyIndicator()
     for src in self.model.sources:
         src.selected = not src.selected
     self.model.emitSelection(self)
     busy.reset_cursor()
Пример #8
0
 def setColorMapNumber(self, index, write_config=True):
     busy = BusyIndicator()
     self._current_cmap_index = index
     cmap = self._cmap_list[index]
     self.image.setColorMap(cmap)
     self.colorMapChanged.emit(cmap)
     if self._config and write_config:
         self._config.set("colour-map-number", index)
     busy.reset_cursor()
Пример #9
0
 def _refreshSelectedItems(self, origin=None):
     busy = BusyIndicator()
     dprint(3, "refreshing selected items")
     for item in self.iterator():
         if item.isSelected():
             dprint(4, "resetting item", item._src.name)
             item.setSource(item._src)
     dprint(3, "refreshing selected items done")
     busy.reset_cursor()
Пример #10
0
 def setIntensityMapNumber(self, index, write_config=True):
     busy = BusyIndicator()
     self._current_imap_index = index
     imap = self._imap_list[index][1]
     imap.setDataSubset(self._displaydata, self._displaydata_minmax)
     imap.setDataRange(*self._displayrange)
     self.image.setIntensityMap(imap)
     self.intensityMapChanged.emit(imap, index)
     if self._config and write_config:
         self._config.set("intensity-map-number", index)
     busy.reset_cursor()
Пример #11
0
 def _displayAllImages(self, enabled):
     busy = BusyIndicator()
     if enabled:
         for ic in self._imagecons:
             ic.setImageVisible(True)
     else:
         self._imagecons[0].setImageVisible(True)
         for ic in self._imagecons[1:]:
             ic.setImageVisible(False)
     self.replot()
     busy.reset_cursor()
Пример #12
0
 def raiseImage(self, imagecon, foo=None):
     busy = None
     # reshuffle image stack, if more than one image image
     if len(self._imagecons) > 1:
         busy = BusyIndicator()
         # reshuffle image stack
         self._imagecons.remove(imagecon)
         self._imagecons.insert(0, imagecon)
         # notify imagecons
         for i, ic in enumerate(self._imagecons):
             label = "%d" % (i + 1) if i else "<B>1</B>"
             ic.setZ(self._z0 - i * 10,
                     top=not i,
                     depthlabel=label,
                     can_raise=True)
         # adjust visibility
         for j, ic in enumerate(self._imagecons):
             ic.setImageVisible(not j
                                or bool(self._qa_plot_all.isChecked()))
         # issue replot signal fixed with assumption that this signal is now correct according to the old version
         # self.imageRaised.emit(self._imagecons[0])  # This was the old signal
         self.imagePlotRaised.emit()
         self.fastReplot()
     # else simply update labels
     else:
         self._imagecons[0].setZ(self._z0,
                                 top=True,
                                 depthlabel=None,
                                 can_raise=False)
         self._imagecons[0].setImageVisible(True)
     # update slice menus
     img = imagecon.image
     axes = imagecon.renderControl().slicedAxes()
     for i, (_next, _prev) in enumerate(self._qa_slices):
         _next.setVisible(False)
         _prev.setVisible(False)
         if i < len(axes):
             iaxis, name, labels = axes[i]
             _next.setVisible(True)
             _prev.setVisible(True)
             _next.setText("Show next slice along %s axis" % name)
             _prev.setText("Show previous slice along %s axis" % name)
     # emit signals
     self.imageRaised.emit(img)
     # if dockable control dialog is docked and tabbed then raise to front
     if imagecon._dockable_colour_ctrl is not None:
         if imagecon._dockable_colour_ctrl.isVisible():
             if not imagecon._dockable_colour_ctrl.isFloating():
                 list_of_tabbed_widgets = self.mainwin.tabifiedDockWidgets(
                     imagecon._dockable_colour_ctrl)
                 if list_of_tabbed_widgets:
                     imagecon._dockable_colour_ctrl.raise_()
     if busy is not None:
         busy.reset_cursor()
Пример #13
0
 def dropEvent(self, event):
     busy = None
     filenames = self._getFilenamesFromDropEvent(event)
     dprint(1, "dropping", filenames)
     if filenames:
         event.acceptProposedAction()
         busy = BusyIndicator()
         for name in filenames:
             self.imgman.loadImage(name)
     if busy is not None:
         busy.reset_cursor()
Пример #14
0
 def show(self):
     dprint(4, "show entrypoint")
     if self._geometry:
         dprint(4, "setting geometry")
         self.setGeometry(self._geometry)
     if self._hist is None:
         busy = BusyIndicator()
         dprint(4, "updating histogram")
         self._updateHistogram()
         dprint(4, "updating stats")
         self._updateStats(self._subset, self._subset_range)
         busy.reset_cursor()
     dprint(4, "calling QDialog.show")
     QDialog.show(self)
Пример #15
0
 def setIntensityMapLogCycles(self,
                              cycles,
                              notify_image=True,
                              write_config=True):
     busy = BusyIndicator()
     imap = self.currentIntensityMap()
     if isinstance(imap, Colormaps.LogIntensityMap):
         imap.log_cycles = cycles
         if notify_image:
             self.image.setIntensityMap()
         self.intensityMapChanged.emit(imap, self._current_imap_index)
     if self._config and write_config:
         self._config.set("intensity-log-cycles", cycles)
     busy.reset_cursor()
Пример #16
0
 def _exportImageToPNG(self, filename=None):
     if not filename:
         if not self._export_png_dialog:
             dialog = self._export_png_dialog = QFileDialog(self, "Export image to PNG", ".", "*.png")
             dialog.setDefaultSuffix("png")
             dialog.setFileMode(QFileDialog.AnyFile)
             dialog.setAcceptMode(QFileDialog.AcceptSave)
             dialog.setModal(True)
             QObject.connect(dialog, SIGNAL("filesSelected(const QStringList &)"), self._exportImageToPNG)
         return self._export_png_dialog.exec_() == QDialog.Accepted
     busy = BusyIndicator()
     if isinstance(filename, QStringList):
         filename = filename[0]
     filename = str(filename)
     # make QPixmap
     nx, ny = self.image.imageDims()
     (l0, l1), (m0, m1) = self.image.getExtents()
     pixmap = QPixmap(nx, ny)
     painter = QPainter(pixmap)
     # use QwtPlot implementation of draw canvas, since we want to avoid caching
     xmap = QwtScaleMap()
     xmap.setPaintInterval(0, nx)
     xmap.setScaleInterval(l1, l0)
     ymap = QwtScaleMap()
     ymap.setPaintInterval(ny, 0)
     ymap.setScaleInterval(m0, m1)
     self.image.draw(painter, xmap, ymap, pixmap.rect())
     painter.end()
     # save to file
     try:
         pixmap.save(filename, "PNG")
     except Exception as exc:
         self.emit(SIGNAL("showErrorMessage"), "Error writing %s: %s" % (filename, str(exc)))
         return
     self.emit(SIGNAL("showMessage"), "Exported image to file %s" % filename)
Пример #17
0
 def _selectAll(self):
     if not self.model:
         return
     busy = BusyIndicator()
     for src in self.model.sources:
         src.selected = True
     self.model.emitSelection(self)
Пример #18
0
 def _updateSlice(self, write_config=True):
     """Common internal method called to finalize changes to _current_slice"""
     busy = BusyIndicator()
     dprint(2, "_updateSlice", self._current_slice, time.time() % 60)
     indices = tuple(self._current_slice)
     self.image.selectSlice(*indices)
     dprint(2, "image slice selected", time.time() % 60)
     img = self.image.image()
     self._slicerange = self._sliceranges.get(indices)
     if self._slicerange is None:
         self._slicerange = self._sliceranges[
             indices] = self.image.imageMinMax()[:2]
     dprint(2, "min/max updated", time.time() % 60)
     self.setSliceSubset(set_display_range=False)
     if write_config and self._config:
         self._config.set("slice", " ".join(map(str, indices)))
     busy.reset_cursor()
Пример #19
0
 def setDisplayRange(self,
                     dmin,
                     dmax,
                     notify_image=True,
                     write_config=True):
     if dmax < dmin:
         dmin, dmax = dmax, dmin
     if (dmin, dmax) != self._displayrange:
         self._displayrange = dmin, dmax
         self.image.intensityMap().setDataRange(dmin, dmax)
         if notify_image:
             busy = BusyIndicator()
             self.image.setIntensityMap(emit=True)
             busy.reset_cursor()
         self.displayRangeChanged.emit(dmin, dmax)
         if self._config and write_config:
             self._config.set("range-min", dmin, save=False)
             self._config.set("range-max", dmax)
Пример #20
0
 def _changeDisplayRangeToPercent(self, percent):
     busy = BusyIndicator()
     if self._hist is None:
         self._updateHistogram()
         self._updateStats(self._subset, self._subset_range)
     # delta: we need the [delta,100-delta] interval of the total distribution
     delta = self._subset.size * ((100. - percent) / 200.)
     # get F(x): cumulative sum
     cumsum = numpy.zeros(len(self._hist_hires) + 1, dtype=int)
     cumsum[1:] = numpy.cumsum(self._hist_hires)
     bins = numpy.zeros(len(self._hist_hires) + 1, dtype=float)
     bins[0] = self._subset_range[0]
     bins[1:] = self._hist_bins_hires + self._hist_binsize_hires / 2
     # use interpolation to find value interval corresponding to [delta,100-delta] of the distribution
     dprint(2, self._subset.size, delta, self._subset.size - delta)
     dprint(2, cumsum, self._hist_bins_hires)
     # if first bin is already > delta, then set colour range to first bin
     x0, x1 = numpy.interp([delta, self._subset.size - delta], cumsum, bins)
     # and change the display range (this will also cause a histplot.replot() via _updateDisplayRange above)
     self._rc.setDisplayRange(x0, x1)
     busy.reset_cursor()
Пример #21
0
 def _saveImage(self):
     filename = QFileDialog.getSaveFileName(
         self,
         "Save FITS file",
         self._save_dir,
         "FITS files(*.fits *.FITS *fts *FTS)",
         options=QFileDialog.DontUseNativeDialog)
     filename = str(filename[0])
     if not filename:
         return
     busy = BusyIndicator()
     self._imgman.signalShowMessage.emit(
         """Writing FITS image %s""" % filename, 3000)
     QApplication.flush()
     try:
         self.image.save(filename)
     except Exception as exc:
         busy.reset_cursor()
         traceback.print_exc()
         self._imgman.signalShowErrorMessage.emit(
             """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.reset_cursor()
Пример #22
0
 def saveFile(self,
              filename=None,
              confirm=False,
              overwrite=True,
              non_native=False):
     """Saves file using the specified 'filename'. If filename is None, uses current filename, if
     that is not set, goes to saveFileAs() to open dialog and get a filename.
     If overwrite=False, will ask for confirmation before overwriting an existing file.
     If non_native=False, will ask for confirmation before exporting in non-native format.
     If confirm=True, will ask for confirmation regardless.
     Returns True if saving succeeded, False on error (or if cancelled by user).
     """
     if isinstance(filename, QStringList):
         filename = filename[0]
     filename = (filename and str(filename)) or self.filename
     if filename is None:
         return self.saveFileAs()
     else:
         warning = ''
         # try to determine the file type
         filetype, import_func, export_func, doc = Tigger.Models.Formats.resolveFormat(
             filename, None)
         if export_func is None:
             self.signalShowErrorMessage.emit(
                 """Error saving model file %s: unsupported output format"""
                 % filename)
             return
         if os.path.exists(filename) and not overwrite:
             warning += "<P>The file already exists and will be overwritten.</P>"
         if filetype != 'Tigger' and not non_native:
             warning += """<P>Please note that you are exporting the model using the external format '%s'.
           Source types, tags and other model features not supported by this
           format will be omitted during the export.</P>""" % filetype
         # get confirmation
         if confirm or warning:
             dialog = QMessageBox.warning if warning else QMessageBox.question
             if dialog(self, "Saving sky model",
                       "<P>Save model to %s?</P>%s" % (filename, warning),
                       QMessageBox.Save | QMessageBox.Cancel,
                       QMessageBox.Save) != QMessageBox.Save:
                 return False
         busy = BusyIndicator()
         try:
             export_func(self.model, filename)
             self.model.setFilename(filename)
         except:
             busy.reset_cursor()
             self.signalShowErrorMessage.emit(
                 """Error saving model file %s: %s""" %
                 (filename, str(sys.exc_info()[1])))
             return False
         else:
             self.signalShowMessage.emit(
                 """Saved model to file %s""" % filename, 3000)
             self._display_filename = os.path.basename(filename)
             self._indicateModelUpdated(updated=False)
             self.filename = filename
             return True
         finally:
             busy.reset_cursor()
Пример #23
0
 def accept(self):
     """Tries to restore the image, and closes the dialog if successful."""
     # get list of sources to restore
     sources = self.model.sources
     sel_sources = [src for src in sources if src.selected]
     if len(sel_sources) > 0 and len(sel_sources) < len(sources) and self.wselonly.isChecked():
         sources = sel_sources
     if not sources:
         self.qerrmsg.showMessage("No sources to restore.")
         return
     busy = BusyIndicator()
     # get filenames
     infile = self.wfile_in.filename()
     outfile = self.wfile_out.filename()
     self.parent().showMessage(
         "Restoring %d model sources to image %s, writing to %s" % (len(sources), infile, outfile))
     # read fits file
     try:
         input_hdu = pyfits.open(infile)[0]
     except Exception as err:
         busy = None
         self.qerrmsg.showMessage("Error reading FITS file %s: %s" % (infile, str(err)))
         return
     # get beam sizes
     try:
         bmaj = float(str(self.wbmaj.text()))
         bmin = float(str(self.wbmin.text()))
         pa = float(str(self.wbpa.text()) or "0")
     except Exception as err:
         busy = None
         self.qerrmsg.showMessage("Invalid beam size specified")
         return
     bmaj = bmaj / (Imaging.FWHM * 3600) * DEG
     bmin = bmin / (Imaging.FWHM * 3600) * DEG
     pa = pa * DEG
     # restore
     try:
         Imaging.restoreSources(input_hdu, sources, bmaj, bmin, pa)
     except Exception as err:
         busy = None
         self.qerrmsg.showMessage("Error restoring model into image: %s" % str(err))
         return
     # save fits file
     try:
         input_hdu.writeto(outfile, clobber=True)
     except Exception as err:
         busy = None
         self.qerrmsg.showMessage("Error writing FITS file %s: %s" % (outfile, str(err)))
         return
     self.parent().loadImage(outfile)
     busy = None
     return QDialog.accept(self)
Пример #24
0
 def _select_threshold(self, *dum):
     dprint(1, "select_threshold", dum)
     self._in_select_threshold = True
     busy = BusyIndicator()
     try:
         # get threshold, ignore if not set
         threshold = str(self.wthreshold.text())
         if not threshold:
             self._reset_percentile()
             return
         # try to parse threshold, ignore if invalid
         try:
             threshold = float(threshold)
         except:
             self._reset_percentile()
             return
         # get comparison operator
         op, select = self.Operators[str(self.wgele.currentText())]
         # apply to initial segment (that matches operator)
         for num, entry in enumerate(self._sort_index):
             if not op(entry, threshold):
                 break
             entry[1].selected = select
         else:
             num = len(self._sort_index)
         # apply to remaining segment
         for val, src, cumsum in self._sort_index[num:]:
             src.selected = not select
         # set percentile
         percent = round(float(num * 100) / len(self._sort_index))
         if not select:
             percent = 100 - percent
         self.wpercent.setValue(percent)
         self.wpercent_lbl.setText("%3d%%" % percent)
         # emit signal
         self.model.emitSelection(self)
     finally:
         self._in_select_threshold = False
         busy.reset_cursor()
Пример #25
0
 def _psfFileSelected(self, filename):
     busy = BusyIndicator()
     filename = str(filename)
     self.parent().showMessage("Fitting gaussian to PSF file %s" % filename)
     try:
         bmaj, bmin, pa = [x / DEG for x in Imaging.fitPsf(filename)]
     except Exception as err:
         busy = None
         self.qerrmsg.showMessage("Error fitting PSF file %s: %s" % (filename, str(err)))
         return
     bmaj *= 3600 * Imaging.FWHM
     bmin *= 3600 * Imaging.FWHM
     self.wbmaj.setText(str(bmaj))
     self.wbmin.setText(str(bmin))
     self.wbpa.setText(str(pa))
Пример #26
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.signalShowErrorMessage.emit(
             """Error loading model file %s: unknown file format""" %
             _filename)
         return
     # try to load the specified file
     busy = BusyIndicator()
     self.signalShowMessage.emit(
         """Reading %s file %s""" % (filetype, _filename), 3000)
     QApplication.flush()
     try:
         model = import_func(_filename)
         model.setFilename(_filename)
     except:
         busy.reset_cursor()
         self.signalShowErrorMessage.emit(
             """Error loading '%s' file %s: %s""" %
             (filetype, _filename, str(sys.exc_info()[1])))
         return
     else:
         # set the layout
         if _show:
             self.setLayout(self.LayoutImageModel)
         # add to content
         if _merge and self.model:
             self.model.addSources(model.sources)
             self.signalShowMessage.emit(
                 """Merged in %d sources from '%s' file %s""" %
                 (len(model.sources), filetype, _filename), 3000)
             self.model.emitUpdate(SkyModel.SkyModel.UpdateAll)
         else:
             print("""Loaded %d sources from '%s' file %s""" %
                   (len(model.sources), filetype, _filename))
             self.signalShowMessage.emit(
                 """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
     finally:
         busy.reset_cursor()
Пример #27
0
 def saveSelectionAs(self, filename=None, force=False):
     if not self.model:
         return
     if filename is None:
         if not self._save_sel_as_dialog:
             filters = ";;".join([
                 "%s (%s)" % (name, " ".join(patterns))
                 for name, patterns, func in self._save_file_types
             ])
             dialog = self._save_sel_as_dialog = QFileDialog(
                 self, "Save sky model", ".", filters)
             dialog.setDefaultSuffix(ModelHTML.DefaultExtension)
             dialog.setFileMode(QFileDialog.AnyFile)
             dialog.setAcceptMode(QFileDialog.AcceptSave)
             dialog.setOption(QFileDialog.DontConfirmOverwrite, False)
             dialog.setModal(True)
             dialog.filesSelected['QStringList'].connect(
                 self.saveSelectionAs)
         return self._save_sel_as_dialog.exec_() == QDialog.Accepted
     # save selection
     if isinstance(filename, QStringList):
         filename = filename[0]
     filename = str(filename)
     selmodel = self.model.copy()
     sources = [src for src in self.model.sources if src.selected]
     if not sources:
         self.signalShowErrorMessage.emit(
             """You have not selected any sources to save.""")
         return
     # try to determine the file type
     filetype, import_func, export_func, doc = Tigger.Models.Formats.resolveFormat(
         filename, None)
     if export_func is None:
         self.signalShowErrorMessage.emit(
             """Error saving model file %s: unsupported output format""" %
             filename)
         return
     busy = BusyIndicator()
     try:
         export_func(self.model, filename, sources=sources)
     except:
         busy.reset_cursor()
         self.signalShowErrorMessage.emit(
             """Error saving selection to model file %s: %s""" %
             (filename, str(sys.exc_info()[1])))
         return False
     else:
         self.signalShowMessage.emit(
             """Wrote %d selected source%s to file %s""" %
             (len(selmodel.sources),
              "" if len(selmodel.sources) == 1 else "s", filename), 3000)
     finally:
         busy.reset_cursor()
     pass
Пример #28
0
 def _fileSelected(self, filename, quiet=False):
     self.wokbtn.setEnabled(False)
     if not filename:
         return None
     # check that filename matches model
     if not os.path.samefile(self._model_dir, os.path.dirname(filename)):
         self.wfile.setFilename('')
         if not quiet:
             QMessageBox.warning(
                 self, "Directory mismatch",
                 """<P>The FITS file must reside in the same directory
       as the current sky model.</P>""")
         self.wfile.setDirectory(self._model_dir)
         return None
     # read fits file
     busy = BusyIndicator()
     try:
         input_hdu = pyfits.open(filename)[0]
         hdr = input_hdu.header
         # get frequency, if specified
         for axis in range(1, hdr['NAXIS'] + 1):
             if hdr['CTYPE%d' % axis].upper() == 'FREQ':
                 self.wfreq.setText(str(hdr['CRVAL%d' % axis] / 1e+6))
                 break
     except Exception as err:
         busy = None
         self.wfile.setFilename('')
         if not quiet:
             QMessageBox.warning(
                 self, "Error reading FITS",
                 "Error reading FITS file %s: %s" % (filename, str(err)))
         return None
     self.wokbtn.setEnabled(True)
     # if filename is not in model already, enable the "add to model" control
     for src in self.model.sources:
         if isinstance(getattr(src, 'shape', None), ModelClasses.FITSImage) \
                 and os.path.exists(src.shape.filename) and os.path.exists(filename) \
                 and os.path.samefile(src.shape.filename, filename):
             self.wadd.setChecked(True)
             self.wadd.setEnabled(False)
             self.wadd.setText("image already in sky model")
             break
     else:
         self.wadd.setText("add image to sky model")
     return filename
Пример #29
0
 def raiseImage(self, imagecon):
     # reshuffle image stack, if more than one image image
     if len(self._imagecons) > 1:
         busy = BusyIndicator()
         # reshuffle image stack
         self._imagecons.remove(imagecon)
         self._imagecons.insert(0, imagecon)
         # notify imagecons
         for i, ic in enumerate(self._imagecons):
             label = "%d" % (i + 1) if i else "<B>1</B>"
             ic.setZ(self._z0 - i * 10,
                     top=not i,
                     depthlabel=label,
                     can_raise=True)
         # adjust visibility
         for j, ic in enumerate(self._imagecons):
             ic.setImageVisible(not j
                                or bool(self._qa_plot_all.isChecked()))
         # issue replot signal
         self.emit(SIGNAL("imageRaised"))
         self.fastReplot()
     # else simply update labels
     else:
         self._imagecons[0].setZ(self._z0,
                                 top=True,
                                 depthlabel=None,
                                 can_raise=False)
         self._imagecons[0].setImageVisible(True)
     # update slice menus
     img = imagecon.image
     axes = imagecon.renderControl().slicedAxes()
     for i, (next, prev) in enumerate(self._qa_slices):
         next.setVisible(False)
         prev.setVisible(False)
         if i < len(axes):
             iaxis, name, labels = axes[i]
             next.setVisible(True)
             prev.setVisible(True)
             next.setText("Show next slice along %s axis" % name)
             prev.setText("Show previous slice along %s axis" % name)
     # emit signasl
     self.emit(SIGNAL("imageRaised"), img)
Пример #30
0
 def accept(self):
     """Tries to make a brick, and closes the dialog if successful."""
     sources = [
         src for src in self.model.sources
         if src.selected and src.typecode == 'pnt'
     ]
     filename = self.wfile.filename()
     if not self._fileSelected(filename):
         return
     # get PB expression
     pbfunc = None
     if self.wpb_apply.isChecked():
         pbexp = str(self.wpb_exp.text())
         try:
             pbfunc = eval("lambda r,fq:" + pbexp)
         except Exception as err:
             QMessageBox.warning(
                 self, "Error parsing PB experssion",
                 "Error parsing primary beam expression %s: %s" %
                 (pbexp, str(err)))
             return
     # get frequency
     freq = str(self.wfreq.text())
     freq = float(freq) * 1e+6 if freq else None
     # get pad factor
     pad = str(self.wpad.text())
     pad = max(float(pad), 1) if pad else 1
     # read fits file
     busy = BusyIndicator()
     try:
         input_hdu = pyfits.open(filename)[0]
     except Exception as err:
         busy = None
         QMessageBox.warning(
             self, "Error reading FITS",
             "Error reading FITS file %s: %s" % (filename, str(err)))
         return
     # reset data if asked to
     if self.woverwrite.isChecked():
         input_hdu.data[...] = 0
     # insert sources
     Imaging.restoreSources(input_hdu,
                            sources,
                            0,
                            primary_beam=pbfunc,
                            freq=freq)
     # save fits file
     try:
         # pyfits seems to produce an exception:
         #         TypeError: formatwarning() takes exactly 4 arguments (5 given)
         # when attempting to overwrite a file. As a workaround, remove the file first.
         if os.path.exists(filename):
             os.remove(filename)
         input_hdu.writeto(filename)
     except Exception as err:
         traceback.print_exc()
         busy = None
         QMessageBox.warning(
             self, "Error writing FITS",
             "Error writing FITS file %s: %s" % (filename, str(err)))
         return
     changed = False
     sources = self.model.sources
     # remove sources from model if asked to
     if self.wdel.isChecked():
         sources = [
             src for src in sources
             if not (src.selected and src.typecode == 'pnt')
         ]
         changed = True
     # add image to model if asked to
     if self.wadd.isChecked():
         hdr = input_hdu.header
         # get image parameters
         max_flux = float(input_hdu.data.max())
         wcs = WCS(hdr, mode='pyfits')
         # Get reference pixel coordinates
         # wcs.getCentreWCSCoords() doesn't work, as that gives us the middle of the image
         # So scan the header to get the CRPIX values
         ra0 = dec0 = 1
         for iaxis in range(hdr['NAXIS']):
             axs = str(iaxis + 1)
             name = hdr.get('CTYPE' + axs, axs).upper()
             if name.startswith("RA"):
                 ra0 = hdr.get('CRPIX' + axs, 1) - 1
             elif name.startswith("DEC"):
                 dec0 = hdr.get('CRPIX' + axs, 1) - 1
         # convert pixel to degrees
         ra0, dec0 = wcs.pix2wcs(ra0, dec0)
         ra0 *= DEG
         dec0 *= DEG
         sx, sy = wcs.getHalfSizeDeg()
         sx *= DEG
         sy *= DEG
         nx, ny = input_hdu.data.shape[-1:-3:-1]
         # check if this image is already contained in the model
         for src in sources:
             if isinstance(getattr(src, 'shape', None),
                           ModelClasses.FITSImage) and os.path.samefile(
                               src.shape.filename, filename):
                 # update source parameters
                 src.pos.ra, src.pos.dec = ra0, dec0
                 src.flux.I = max_flux
                 src.shape.ex, src.shape.ey = sx, sy
                 src.shape.nx, src.shape.ny = nx, ny
                 src.shape.pad = pad
                 break
         # not contained, make new source object
         else:
             pos = ModelClasses.Position(ra0, dec0)
             flux = ModelClasses.Flux(max_flux)
             shape = ModelClasses.FITSImage(sx,
                                            sy,
                                            0,
                                            os.path.basename(filename),
                                            nx,
                                            ny,
                                            pad=pad)
             img_src = SkyModel.Source(os.path.splitext(
                 os.path.basename(filename))[0],
                                       pos,
                                       flux,
                                       shape=shape)
             sources.append(img_src)
         changed = True
     if changed:
         self.model.setSources(sources)
         self.model.emitUpdate(SkyModel.SkyModel.UpdateAll, origin=self)
     self.parent().showMessage("Wrote %d sources to FITS file %s" %
                               (len(sources), filename))
     busy = None
     return QDialog.accept(self)