Skip to content

Commit

Permalink
New read me + debug subtract background
Browse files Browse the repository at this point in the history
  • Loading branch information
vpicouet committed Jun 2, 2021
1 parent 9ece11c commit 44a5cb2
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 82 deletions.
27 changes: 9 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

pyDS9plugin is the first open source pythonic [SAOImageDS9](https://sites.google.com/cfa.harvard.edu/saoimageds9) quick look plugin.

Click on the image to see the 3 minutes youtube presentation video:

[<img src="https://people.lam.fr/picouet.vincent/pyds9plugin/gif/3d2d_new.mov.gif" width="80%"
style="display:block;margin: 0 auto;">](https://www.youtube.com/watch?v=9JzcMCxo6Fk)

The documentation of the extension is available [here](https://nuage.osupytheas.fr/s/Z6D64wRpDkE7wTJ).

SAOImage DS9 is an astronomical imaging and data visualization application. Its 30 years of development has made it very stable and easy to use. This made it an essential tool in all fields of astronomy (observation, simulation, instrumentation). Much more profitable but pretty unsung feature, its extensibility makes it a limitless tool to interact with astronomical data. This extensibility did not generate a large collaborative and well organized effort to develop important extensions that could progressively converge towards a stable/rapid/configurable multi-extension DS9 package.
Expand Down Expand Up @@ -37,7 +42,7 @@ There is not as of yet a separate conda package.
Documentation
-------------

Some documentation is availanle available at [https://people.lam.fr/picouet.vincent/pyds9plugin](https://people.lam.fr/picouet.vincent/index.html).
Some documentation is available available at [https://people.lam.fr/picouet.vincent/pyds9plugin](https://people.lam.fr/picouet.vincent/index.html).


Contributions
Expand All @@ -54,20 +59,6 @@ Features
- Command line access: The package is totally accessible via command line. Run `DS9Utils` to see all the available function and `DS9Utils function -h` to see the help of each function. All the arguments of the functions are parsed through argparse module which makes the functions not only accessible from DS9, but from terminal and python using argv argument.
- Multi-processing: PyDS9plugin is by essence a quicklook plug-in that is perfect to analyze and process images on the fly by changing parameters and so on. But it was important for us to make it suitable for more important pipelines as soon as you are ok with the parameters to use. To this end, most of the functions are compatible with multi-processing so that they can be run on a set of images.
- Multi-operability: Command line access and python import allows to operate the plugin for other pipelines. The plugin for DS9 could actually pretty easily be operated by other visualization softwares like ginga or glueviz.

- Python interpreter/macros:


<img src="https://people.lam.fr/picouet.vincent/pyds9plugin/gif/python.mov.gif" width="80%"
style="display:block;margin: 0 auto;">
- VTK 3D rendering:


<img src="https://people.lam.fr/picouet.vincent/pyds9plugin/gif/3d2d_new.mov.gif" width="80%"
style="display:block;margin: 0 auto;">

- Interactive profile fitting :


<img src="https://people.lam.fr/picouet.vincent/pyds9plugin/gif/fitinter.mov.gif" width="80%"
style="display:block;margin: 0 auto;">
- Python interpreter/macros
- VTK 3D rendering
- Interactive profile fitting
129 changes: 69 additions & 60 deletions pyds9plugin/DS9Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -791,14 +791,24 @@ def LoadDS9QuickLookPlugin(xpapoint=None):
return


def ReplaceStringInFile(path, string1, string2):
def ReplaceStringInFile(path, string1, string2,path2=None):
"""Replaces string in a txt file"""
fin = open(path, "rt")
data = fin.read()
data = data.replace(string1, string2)
fin.close()
if path2 is not None:
path = path2
if os.path.exists(path):
os.remove(path)
fin = open(path, "x")
else:
# try:
fin = open(path, "wt")
# except FileNotFoundError:
# fin = open(path, "x")

fin = open(path, "wt")
# fin = open(path, "w")
fin.write(data)
fin.close()
return
Expand Down Expand Up @@ -866,11 +876,11 @@ def setup(xpapoint=None, config=my_conf, color="cool",argv=[]):
# verboseprint("%s - %s - %s - %s - %s - %s" % (scale, cuts, smooth, color, invert, grid))
cuts = np.array(args.limits.split("-"), dtype=float)
region = getregion(d, all=False, quick=True, selected=True)
if region is None:
image_area = [0, -1, 0, -1]
else:
image_area = Lims_from_region(None, coords=region)
Xinf, Xsup, Yinf, Ysup = image_area
# if region is None:
# image_area = [0, -1, 0, -1]
# else:

# print(Xinf, Xsup, Yinf, Ysup)
# verboseprint(Xinf, Xsup, Yinf, Ysup)
from astropy.io import fits
# from tqdm import tqdm
Expand All @@ -887,14 +897,25 @@ def setup(xpapoint=None, config=my_conf, color="cool",argv=[]):
fitsimage = d.get_pyfits()
fitsimage = fitsimage[FitsExt(fitsimage)].data
lx, ly = fitsimage.shape[0], fitsimage.shape[1]
if region is None:
# verboseprint("No region defined, big image, taking the center.")
if region is not None:
image_area = Lims_from_region(None, coords=region)
Xinf, Xsup, Yinf, Ysup = image_area
if (Xsup<0) | (Ysup<0):
image_area = [int(lx / 2), int(lx / 2) + 50, int(ly / 2), int(ly / 2) + 50]
else:
image_area = [int(lx / 2), int(lx / 2) + 50, int(ly / 2), int(ly / 2) + 50]
Xinf, Xsup, Yinf, Ysup = image_area
# print(image_area)
# if region is None:
# # verboseprint("No region defined, big image, taking the center.")
# image_area = [int(lx / 2), int(lx / 2) + 50, int(ly / 2), int(ly / 2) + 50]
image = fitsimage[Yinf:Ysup, Xinf:Xsup]
try:
# print('ok')
image_ok = image[np.isfinite(image)]
d.set("cmap %s ; scale %s ; scale limits %0.3f %0.3f " % (args.color, args.scale, np.nanpercentile(image_ok, cuts[0]), np.nanpercentile(image_ok, cuts[1])))
except ValueError:
# print('error')
d.set("cmap %s ; scale %s " % (args.color, args.scale))

return
Expand Down Expand Up @@ -3247,6 +3268,8 @@ def SmoothCallback(value):
def change_contour():
p.update_coordinates(d["points"], mesh=mesh)
p.update_coordinates(d["points"], mesh=mesh_c)
# p.update_scalars(d["points"], mesh=mesh)
# p.update_scalars(d["points"], mesh=mesh_c)
if d["Contour"]:
if d["smooth"] is True:
p.update_coordinates(mesh_c.contour().points, mesh=contours_c)
Expand Down Expand Up @@ -5848,11 +5871,8 @@ def background_estimation(xpapoint=None, n=2, DS9backUp=DS9_BackUp_path, Plot=Tr
sigma, percentile, snr, npixels, dilate = np.array([sigma, percentile, snr, npixels, dilate], dtype=int)
box1, box2 = np.array(boxs.split(","), dtype=int)
path = globglob(args.path)
jobs = []
manager = Manager()
return_dict = manager.dict()
if len(path) > 1:
Plot = False
# if len(path) > 1:
# Plot = False
name = Parallelize(function=BackgroundEstimationPhot, parameters=[ float(sigma), bckd, rms, (filter1, filter2), (box1, box2), n, DS9_BackUp_path, snr, npixels, dilate, percentile, mask, Plot], action_to_paralize=path, number_of_thread=args.number_processors)

# for filename in path:
Expand Down Expand Up @@ -5894,53 +5914,41 @@ def BackgroundEstimationPhot(filename, sigma, bckd, rms, filters, boxs, n=2, DS9
"BiweightLocationBackground": BiweightLocationBackground,
}
functions_rms = {"StdBackgroundRMS": StdBackgroundRMS, "MADStdBackgroundRMS": MADStdBackgroundRMS, "BiweightScaleBackgroundRMS": BiweightScaleBackgroundRMS}
bkg = []
masks = [data]

for i, mask_data in enumerate(masks):
if mask:
mask_source = make_source_mask(mask_data, nsigma=snr, npixels=npixels, dilate_size=dilate_size)
else:
mask_source = np.ones(mask_data.shape, dtype=bool)
bkg_estimator = functions[bckd]()
bkgrms_estimator = functions_rms[rms]()
if len(masks) > 1:
bkg.append(
Background2D(
mask_data, boxs, filter_size=filters, sigma_clip=SigmaClip(sigma=sigma), bkg_estimator=bkg_estimator, exclude_percentile=exclude_percentile, bkgrms_estimator=bkgrms_estimator
)
) # ,mask=mask_source)
else:
bkg.append(
Background2D(
mask_data,
boxs,
filter_size=filters,
sigma_clip=SigmaClip(sigma=sigma),
bkg_estimator=bkg_estimator,
exclude_percentile=exclude_percentile,
bkgrms_estimator=bkgrms_estimator,
mask=mask_source,
)
)
verboseprint("Mask %i, median = %0.2f" % (i, bkg[-1].background_median))
verboseprint("Mask %i, rms = %0.2f" % (i, bkg[-1].background_rms_median))
if i == 0:
fitsfile.data = fitsfile.data - bkg[-1].background # .astype('uint16')
else:
fitsfile.data[np.isfinite(mask)] = fitsfile.data[np.isfinite(mask)] - bkg[-1].background[np.isfinite(mask)] # .astype('uint16')
if len(masks) == 2:
masks[-1][np.isfinite(masks[-1])] = fitsfile.data[np.isfinite(masks[-1])]
if len(masks) == 2:
diff = np.nanmean(fitsfile.data[np.isfinite(masks[1])]) - np.nanmean(fitsfile.data[np.isfinite(masks[0])])
fitsfile.data[np.isfinite(masks[1])] -= diff
diff = np.nanmean(np.hstack((fitsfile.data[np.isfinite(masks[0])], fitsfile.data[np.isfinite(masks[1])])))
fitsfile.data[np.isfinite(masks[1])] -= diff
# i, mask_data = 0, data
# for i, mask_data in enumerate(masks):
if mask:
mask_source = make_source_mask(data, nsigma=snr, npixels=npixels, dilate_size=dilate_size)
else:
diff = np.nanmean(fitsfile.data[np.isfinite(masks[0])])
fitsfile.data[np.isfinite(masks[0])] -= diff
if np.isfinite(data).all():
fitsfile.data = fitsfile.data.astype("uint16")
mask_source = np.ones(data.shape, dtype=bool)
bkg_estimator = functions[bckd]()
bkgrms_estimator = functions_rms[rms]()
bkg = Background2D(
data,
boxs,
filter_size=filters,
sigma_clip=SigmaClip(sigma=sigma),
bkg_estimator=bkg_estimator,
exclude_percentile=exclude_percentile,
bkgrms_estimator=bkgrms_estimator,
mask=mask_source)
verboseprint("Mask, median = %0.2f" % (bkg.background_median))
verboseprint("Mask, rms = %0.2f" % (bkg.background_rms_median))
# if i == 0:
fitsfile.data = fitsfile.data - bkg.background # .astype('uint16')
# else:
# fitsfile.data[np.isfinite(mask)] = fitsfile.data[np.isfinite(mask)] - bkg[-1].background[np.isfinite(mask)] # .astype('uint16')
# if len(masks) == 2:
# masks[-1][np.isfinite(masks[-1])] = fitsfile.data[np.isfinite(masks[-1])]
# if len(masks) == 2:
# diff = np.nanmean(fitsfile.data[np.isfinite(masks[1])]) - np.nanmean(fitsfile.data[np.isfinite(masks[0])])
# fitsfile.data[np.isfinite(masks[1])] -= diff
# diff = np.nanmean(np.hstack((fitsfile.data[np.isfinite(masks[0])], fitsfile.data[np.isfinite(masks[1])])))
# fitsfile.data[np.isfinite(masks[1])] -= diff
# else:
# diff = np.nanmean(fitsfile.data[np.isfinite(masks[0])])
# fitsfile.data[np.isfinite(masks[0])] -= diff
# if np.isfinite(data).all():
# fitsfile.data = fitsfile.data.astype("uint16")

name = os.path.join(os.path.dirname(filename) + "/bkgd_photutils_substracted/%s" % (os.path.basename(filename)))
fitswrite(fitsfile, name)
Expand Down Expand Up @@ -9427,6 +9435,7 @@ def python_command(xpapoint=None,argv=[]):
def Button(xpapoint=None):
""" Creates a pyQt5 button to continue the different tutorial on DS9 or quit
"""
#Needs to be installed via mamba install PyQt to be sure it works on OSX, and on linux: sudo apt-get install libxcb-xinerama0
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtCore import pyqtSlot # <--- add this line
Expand Down
2 changes: 1 addition & 1 deletion pyds9plugin/QuickLookPlugIn.ds9.ans
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ hmenu 3. Astronomical Softwares
Subtract Background
*
menu
DS9Utils background_estimation -x $xpa_method $param(Background-Subtraction); -s $sigma -b $bckd -r $rms -f $filter -box $box -per $percentile -m $mask -snr $snr -n $npixels -d $dilate -p - | $text
DS9Utils background_estimation -x $xpa_method $param(Background-Subtraction); -s $sigma -b $bckd -r $rms -f $filter -box $box -per $percentile -m $mask -snr $snr -n $npixels -d $dilate | $text

Aperture photometry
*
Expand Down
2 changes: 1 addition & 1 deletion pyds9plugin/QuickLookPlugIn_DS9<8.2.ds9.ans
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ hmenu 3. Astronomical Softwares
Subtract Background
*
menu
DS9Utils background_estimation -x $xpa_method $param(Background-Subtraction); -s $sigma -b $bckd -r $rms -f $filter -box $box -per $percentile -m $mask -snr $snr -n $npixels -d $dilate -p - | $text
DS9Utils background_estimation -x $xpa_method $param(Background-Subtraction); -s $sigma -b $bckd -r $rms -f $filter -box $box -per $percentile -m $mask -snr $snr -n $npixels -d $dilate | $text

Aperture photometry
*
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

MAJOR = '3'
MINOR = '0'
MICRO = '1dev5'
MICRO = '1dev6'
version = '%s.%s%s' % (MAJOR, MINOR, MICRO)


Expand Down Expand Up @@ -69,7 +69,7 @@ def setup_package():
version=version,
license='CeCILL-B',
install_requires = requires,
long_description= " A python DS9 extension for quicklook processing of astronomical images. This highly interactive extension can be generalized automatically to a set of images to turn the plug-in into a real multi-processing pipeline.",
long_description= long_description,#" A python DS9 extension for quicklook processing of astronomical images. This highly interactive extension can be generalized automatically to a set of images to turn the plug-in into a real multi-processing pipeline.",
url='https://people.lam.fr/picouet.vincent/index.html',
platforms=["Linux", "Mac OS-X", "Unix"],
cmdclass={'install': PostInstallCommand,'develop': PostDevelopCommand},
Expand Down

0 comments on commit 44a5cb2

Please sign in to comment.