Restructure repository and pep8 changes

Also all executables now use argparse for arguments and helpers.
pull/5/head
Pierros Papadeas 2018-05-06 17:45:51 +03:00
parent 626cbbb3df
commit 96389ccdc8
No known key found for this signature in database
GPG Key ID: AB1301B4FCDFF5D4
14 changed files with 389 additions and 292 deletions

View File

@ -11,7 +11,7 @@ from astropy.coordinates import EarthLocation
from astropy.time import Time
from astropy.io import fits
import astropy.units as u
from utils import get_sunset_and_sunrise
from stvid.utils import get_sunset_and_sunrise
import logging
import configparser
import argparse

View File

@ -1,177 +0,0 @@
#!/usr/bin/env python
from __future__ import print_function
import os
import numpy as np
import astropy.units as u
from astropy.io import fits
from astropy import wcs
from astropy.coordinates import SkyCoord,FK5,ICRS
from astropy.time import Time
from scipy import optimize
# Class for the Tycho 2 catalog
class tycho2_catalog:
"""Tycho2 catalog"""
def __init__(self,maxmag=9.0):
hdu=fits.open(os.path.join(os.getenv("ST_DATADIR"),"data/tyc2.fits"))
ra=hdu[1].data.field('RA')*u.deg
dec=hdu[1].data.field('DEC')*u.deg
mag=hdu[1].data.field('MAG_VT')
c=mag<maxmag
self.ra=ra[c]
self.dec=dec[c]
self.mag=mag[c]
# Estimate the WCS from a reference file
def estimate_wcs_from_reference(ref,fname):
# Read header of reference
hdu=fits.open(ref)
hdu[0].header["NAXIS"]=2
w=wcs.WCS(hdu[0].header)
# Get time and position from reference
tref=Time(hdu[0].header["MJD-OBS"],format="mjd",scale="utc")
pref=SkyCoord(ra=w.wcs.crval[0],dec=w.wcs.crval[1],unit="deg",frame="icrs").transform_to(FK5(equinox=tref))
# Read time from target
hdu=fits.open(fname)
t=Time(hdu[0].header["MJD-OBS"],format="mjd",scale="utc")
# Correct wcs
dra=t.sidereal_time("mean","greenwich")-tref.sidereal_time("mean","greenwich")
p=FK5(ra=pref.ra+dra,dec=pref.dec,equinox=t).transform_to(ICRS)
w.wcs.crval=np.array([p.ra.degree,p.dec.degree])
return w
# Match the astrometry and pixel catalog
def match_catalogs(ast_catalog,pix_catalog,w,rmin):
# Select stars towards pointing center
ra,dec=w.wcs.crval*u.deg
d=np.arccos(np.sin(dec)*np.sin(ast_catalog.dec)+np.cos(dec)*np.cos(ast_catalog.dec)*np.cos(ra-ast_catalog.ra))
c=(d<30.0*u.deg)
ra,dec,mag=ast_catalog.ra[c],ast_catalog.dec[c],ast_catalog.mag[c]
# Convert RA/Dec to pixels
pix=w.wcs_world2pix(np.stack((ra,dec),axis=-1),0)
xs,ys=pix[:,0],pix[:,1]
# Loop over stars
nmatch=0
for i in range(len(pix_catalog.x)):
dx=xs-pix_catalog.x[i]
dy=ys-pix_catalog.y[i]
r=np.sqrt(dx*dx+dy*dy)
if np.min(r)<rmin:
j=np.argmin(r)
pix_catalog.ra[i]=ra[j].value
pix_catalog.dec[i]=dec[j].value
pix_catalog.imag[i]=mag[j]
pix_catalog.flag[i]=1
nmatch+=1
return nmatch
# Residual function
def residual(a,x,y,z):
return z-(a[0]+a[1]*x+a[2]*y)
# Fit transformation
def fit_wcs(w,pix_catalog):
x0,y0=w.wcs.crpix
ra0,dec0=w.wcs.crval
dx,dy=pix_catalog.x-x0,pix_catalog.y-y0
# Iterate to remove outliers
nstars=np.sum(pix_catalog.flag==1)
for j in range(10):
w=wcs.WCS(naxis=2)
w.wcs.crpix=np.array([0.0,0.0])
w.wcs.cd=np.array([[1.0,0.0],[0.0,1.0]])
w.wcs.ctype=["RA---TAN","DEC--TAN"]
w.wcs.set_pv([(2,1,45.0)])
c=pix_catalog.flag==1
# Iterate to move crval to crpix location
for i in range(5):
w.wcs.crval=np.array([ra0,dec0])
world=np.stack((pix_catalog.ra,pix_catalog.dec),axis=-1)
pix=w.wcs_world2pix(world,1)
rx,ry=pix[:,0],pix[:,1]
ax,cov_q,infodict,mesg,ierr=optimize.leastsq(residual,[0.0,0.0,0.0],args=(dx[c],dy[c],rx[c]),full_output=1)
ay,cov_q,infodict,mesg,ierr=optimize.leastsq(residual,[0.0,0.0,0.0],args=(dx[c],dy[c],ry[c]),full_output=1)
ra0,dec0=w.wcs_pix2world([[ax[0],ay[0]]],1)[0]
# Compute residuals
drx=ax[0]+ax[1]*dx+ax[2]*dy-rx
dry=ay[0]+ay[1]*dx+ay[2]*dy-ry
dr=np.sqrt(drx*drx+dry*dry)
rms=np.sqrt(np.sum(dr[c]**2)/len(dr[c]))
dr[~c]=1.0
c=(dr<2.0*rms)
pix_catalog.flag[~c]=0
# Break if converged
if np.sum(c)==nstars:
break
nstars=np.sum(c)
# Compute residuals
rmsx=np.sqrt(np.sum(drx[c]**2)/len(drx[c]))
rmsy=np.sqrt(np.sum(dry[c]**2)/len(dry[c]))
# Store header
w=wcs.WCS(naxis=2)
w.wcs.crpix=np.array([x0,y0])
w.wcs.crval=np.array([ra0,dec0])
w.wcs.cd=np.array([[ax[1],ax[2]],[ay[1],ay[2]]])
w.wcs.ctype=["RA---TAN","DEC--TAN"]
w.wcs.set_pv([(2,1,45.0)])
return w,rmsx,rmsy,rms
def add_wcs(fname,w,rmsx,rmsy):
# Read fits
hdu=fits.open(fname)
whdr={"CRPIX1":w.wcs.crpix[0],"CRPIX2":w.wcs.crpix[1],"CRVAL1":w.wcs.crval[0],"CRVAL2":w.wcs.crval[1],"CD1_1":w.wcs.cd[0,0],"CD1_2":w.wcs.cd[0,1],"CD2_1":w.wcs.cd[1,0],"CD2_2":w.wcs.cd[1,1],"CTYPE1":"RA---TAN","CTYPE2":"DEC--TAN","CUNIT1":"DEG","CUNIT2":"DEG","CRRES1":rmsx,"CRRES2":rmsy}
# Add keywords
hdr=hdu[0].header
for k,v in whdr.items():
hdr[k]=v
hdu=fits.PrimaryHDU(header=hdr,data=hdu[0].data)
hdu.writeto(fname,overwrite=True,output_verify="ignore")
return
def calibrate_from_reference(fname,ref,pix_catalog):
# Estimated WCS
w=estimate_wcs_from_reference(ref,fname)
# Default rms values
rmsx=0.0
rmsy=0.0
# Read catalogs
if (pix_catalog.nstars>4):
ast_catalog=tycho2_catalog(10.0)
# Match catalogs
nmatch=match_catalogs(ast_catalog,pix_catalog,w,10.0)
# Fit transformation
if nmatch>4:
w,rmsx,rmsy,rms=fit_wcs(w,pix_catalog)
# Add wcs
add_wcs(fname,w,rmsx,rmsy)
return w,rmsx,rmsy

View File

@ -1,13 +0,0 @@
#!/bin/bash
# Sleep
sleep 10
# Does /dev/video1 exist
ls -l /dev/video1 >/tmp/camera_1.log 2>&1
# Run mplayer for 10 frames to setup easycap
mplayer -frames 10 tv:// -tv device=/dev/video1 >/tmp/camera_1.log 2>&1
# Start script
python ./acquire.py 1 >/tmp/camera_1.log 2>&1 &

View File

@ -1,13 +0,0 @@
#!/bin/bash
# Sleep
sleep 10
# Does /dev/video2 exist
ls -l /dev/video2 >/tmp/camera_2.log 2>&1
# Run mplayer for 10 frames to setup easycap
mplayer -frames 10 tv:// -tv device=/dev/video2 >/tmp/camera_2.log 2>&1
# Start script
python ./acquire.py 2 >/tmp/camera_2.log 2>&1 &

37
extract_tracks.py 100644 → 100755
View File

@ -1,13 +1,14 @@
#!/usr/bin/env python
import time
import os
import glob
import shutil
from stio import fourframe, satid, observation
from stvid.stio import fourframe, satid, observation
import numpy as np
import ppgplot as ppg
from scipy import optimize, ndimage
import configparser
import argparse
# Gaussian model
@ -454,15 +455,35 @@ if __name__ == '__main__':
# Minimum track points
ntrkmin = 10
# Read commandline options
conf_parser = argparse.ArgumentParser(description='Extract satellite' +
' tracks from frames.')
conf_parser.add_argument("-c", "--conf_file",
help="Specify configuration file. If no file" +
" is specified 'configuration.ini' is used.",
metavar="FILE")
conf_parser.add_argument("-d", "--directory",
help="Specify directory of observations. If no" +
" directory is specified parent will be used.",
metavar='DIR', dest='file_dir', default=".")
args = conf_parser.parse_args()
# Process commandline options and parse configuration
cfg = configparser.ConfigParser(inline_comment_prefixes=('#', ';'))
if args.conf_file:
cfg.read([args.conf_file])
else:
cfg.read('configuration.ini')
# Create output dirs
path = os.getenv("ST_OBSDIR")+"/"+time.strftime("%Y%m%d/%H%M%S",
time.gmtime())
os.makedirs(path+"/classfd")
os.makedirs(path+"/catalog")
os.makedirs(path+"/unid")
path = args.file_dir
os.makedirs(path+"classfd")
os.makedirs(path+"catalog")
os.makedirs(path+"unid")
# Get files
files = sorted(glob.glob("2*.fits"))
files = sorted(glob.glob(path+"2*.fits"))
# Process files
for file in files:

62
imgstat.py 100644 → 100755
View File

@ -4,38 +4,66 @@ import numpy as np
from astropy.io import ascii
import matplotlib.pyplot as plt
import astropy.units as u
from astropy.coordinates import SkyCoord,FK5,AltAz,EarthLocation
from astropy.coordinates import SkyCoord, AltAz, EarthLocation
from astropy.time import Time
import configparser
import argparse
table=ascii.read("imgstat.csv",format="csv")
# Read commandline options
conf_parser = argparse.ArgumentParser(description='Plot image statistics')
conf_parser.add_argument("-c", "--conf_file",
help="Specify configuration file. If no file" +
" is specified 'configuration.ini' is used.",
metavar="FILE")
conf_parser.add_argument("-i", "--input",
help="Specify file to be processed. If no file" +
" is specified ./imgstat.csv will be used.",
metavar='FILE', default="./imgstat.csv")
conf_parser.add_argument("-o", "--output",
help="Specify output file. Default is 'imgstat.png'",
metavar='FILE', default="./imgstat.png")
t=Time(table['mjd'],format="mjd",scale="utc")
pos=SkyCoord(ra=table['ra'],dec=table['de'],frame="icrs",unit="deg")
args = conf_parser.parse_args()
loc=EarthLocation(lat=52.8344*u.deg,lon=6.3785*u.deg,height=10*u.m)
# Process commandline options and parse configuration
cfg = configparser.ConfigParser(inline_comment_prefixes=('#', ';'))
if args.conf_file:
cfg.read([args.conf_file])
else:
cfg.read('configuration.ini')
pa=pos.transform_to(AltAz(obstime=t,location=loc))
table = ascii.read(args.input, format="csv")
mjd0=np.floor(np.min(table['mjd']))
t = Time(table['mjd'], format="mjd", scale="utc")
pos = SkyCoord(ra=table['ra'], dec=table['de'], frame="icrs", unit="deg")
plt.figure(figsize=(20,10))
# Set location
loc = EarthLocation(lat=cfg.getfloat('Common', 'observer_lat')*u.deg,
lon=cfg.getfloat('Common', 'observer_lon')*u.deg,
height=cfg.getfloat('Common', 'observer_el')*u.m)
pa = pos.transform_to(AltAz(obstime=t, location=loc))
mjd0 = np.floor(np.min(table['mjd']))
plt.figure(figsize=(20, 10))
plt.subplot(411)
plt.plot(table['mjd']-mjd0,table['mean'],label='Brightness')
plt.plot(table['mjd']-mjd0,table['std'],label='Variation')
plt.plot(table['mjd']-mjd0, table['mean'], label='Brightness')
plt.plot(table['mjd']-mjd0, table['std'], label='Variation')
plt.ylabel("ADU")
plt.legend()
plt.subplot(412)
plt.plot(table['mjd']-mjd0,pa.az.degree)
plt.plot(table['mjd']-mjd0, pa.az.degree)
plt.ylabel("Azimuth (deg)")
plt.subplot(413)
plt.plot(table['mjd']-mjd0,pa.alt.degree)
plt.plot(table['mjd']-mjd0, pa.alt.degree)
plt.ylabel("Altitude (deg)")
plt.subplot(414)
plt.plot(table['mjd']-mjd0,table['rmsx'],label='RA')
plt.plot(table['mjd']-mjd0,table['rmsy'],label='Dec')
plt.ylim(0,60)
plt.plot(table['mjd']-mjd0, table['rmsx'], label='RA')
plt.plot(table['mjd']-mjd0, table['rmsy'], label='Dec')
plt.ylim(0, 60)
plt.ylabel("Residual (arcseconds)")
plt.xlabel("MJD - %.0f"%mjd0)
plt.xlabel("MJD - %.0f" % mjd0)
plt.legend()
plt.savefig("imgstat.png")
plt.savefig(args.output)

65
process.py 100644 → 100755
View File

@ -2,46 +2,79 @@
from __future__ import print_function
import glob
import numpy as np
from stio import fourframe
from stars import pixel_catalog, generate_star_catalog
from astrometry import calibrate_from_reference
from stvid.stio import fourframe
from stvid.stars import generate_star_catalog
from stvid.astrometry import calibrate_from_reference
import astropy.units as u
from astropy.utils.exceptions import AstropyWarning
from astropy.coordinates import EarthLocation, AltAz
from astropy.coordinates import EarthLocation
import warnings
import configparser
import argparse
if __name__ == "__main__":
# Read commandline options
conf_parser = argparse.ArgumentParser(description='Process captured' +
' video frames.')
conf_parser.add_argument("-c", "--conf_file",
help="Specify configuration file. If no file" +
" is specified 'configuration.ini' is used.",
metavar="FILE")
conf_parser.add_argument("-d", "--directory",
help="Specify directory of observations. If no" +
" directory is specified parent will be used.",
metavar='DIR', dest='file_dir', default=".")
args = conf_parser.parse_args()
# Process commandline options and parse configuration
cfg = configparser.ConfigParser(inline_comment_prefixes=('#', ';'))
if args.conf_file:
cfg.read([args.conf_file])
else:
cfg.read('configuration.ini')
# Set warnings
warnings.filterwarnings("ignore", category=UserWarning, append=True)
warnings.simplefilter("ignore", AstropyWarning)
# Set location
loc=EarthLocation(lat=52.8344*u.deg,lon=6.3785*u.deg,height=10*u.m)
loc = EarthLocation(lat=cfg.getfloat('Common', 'observer_lat')*u.deg,
lon=cfg.getfloat('Common', 'observer_lon')*u.deg,
height=cfg.getfloat('Common', 'observer_el')*u.m)
# Get files
files=sorted(glob.glob("2*.fits"))
files = sorted(glob.glob(args.file_dir+"2*.fits"))
# Statistics file
fstat=open("imgstat.csv","w")
fstat = open(args.file_dir+"imgstat.csv", "w")
fstat.write("fname,mjd,ra,de,rmsx,rmsy,mean,std,nstars,nused\n")
# Loop over files
for fname in files:
# Generate star catalog
pix_catalog=generate_star_catalog(fname)
pix_catalog = generate_star_catalog(fname)
# Calibrate astrometry
calibrate_from_reference(fname,"test.fits",pix_catalog)
calibrate_from_reference(fname, args.file_dir+"test.fits", pix_catalog)
# Stars available and used
nused=np.sum(pix_catalog.flag==1)
nstars=pix_catalog.nstars
nused = np.sum(pix_catalog.flag == 1)
nstars = pix_catalog.nstars
# Get properties
ff=fourframe(fname)
print("%s,%.8lf,%.6f,%.6f,%.3f,%.3f,%.3f,%.3f,%d,%d"%(ff.fname,ff.mjd,ff.crval[0],ff.crval[1],3600*ff.crres[0],3600*ff.crres[1],np.mean(ff.zavg),np.std(ff.zavg),nstars,nused))
fstat.write("%s,%.8lf,%.6f,%.6f,%.3f,%.3f,%.3f,%.3f,%d,%d\n"%(ff.fname,ff.mjd,ff.crval[0],ff.crval[1],3600*ff.crres[0],3600*ff.crres[1],np.mean(ff.zavg),np.std(ff.zavg),nstars,nused))
ff = fourframe(fname)
print(("%s,%.8lf,%.6f,%.6f,%.3f,%.3f," +
"%.3f,%.3f,%d,%d") % (ff.fname, ff.mjd, ff.crval[0],
ff.crval[1], 3600*ff.crres[0],
3600*ff.crres[1], np.mean(ff.zavg),
np.std(ff.zavg), nstars, nused))
fstat.write(("%s,%.8lf,%.6f,%.6f,%.3f,%.3f,%.3f," +
"%.3f,%d,%d\n") % (ff.fname, ff.mjd, ff.crval[0],
ff.crval[1], 3600*ff.crres[0],
3600*ff.crres[1], np.mean(ff.zavg),
np.std(ff.zavg), nstars, nused))
fstat.close()

View File

@ -3,3 +3,10 @@ numpy==1.14.2
opencv-python==3.4.0.12
scipy==1.0.1
git+https://github.com/cbassa/ppgplot.git@master
cycler==0.10.0
kiwisolver==1.0.1
matplotlib==2.2.2
pyparsing==2.2.0
python-dateutil==2.7.2
pytz==2018.4
six==1.11.0

View File

@ -1,47 +0,0 @@
#!/usr/bin/env python
from __future__ import print_function
import os
import subprocess
import numpy as np
class pixel_catalog:
"""Pixel catalog"""
def __init__(self,fname):
d=np.loadtxt(fname)
if len(d.shape)==2:
self.x=d[:,0]
self.y=d[:,1]
self.mag=d[:,2]
self.ra=np.empty_like(self.x)
self.dec=np.empty_like(self.x)
self.imag=np.empty_like(self.x)
self.flag=np.zeros_like(self.x)
self.nstars=len(self.mag)
else:
self.x=None
self.y=None
self.mag=None
self.ra=None
self.dec=None
self.imag=None
self.flag=None
self.nstars=0
def generate_star_catalog(fname):
# Skip if file already exists
if not os.path.exists(fname+".cat"):
# Get sextractor location
env=os.getenv("ST_DATADIR")
# Format command
command="sextractor %s -c %s/sextractor/default.sex"%(fname,env)
# Run sextractor
output=subprocess.check_output(command,shell=True,stderr=subprocess.STDOUT)
# Rename file
if os.path.exists("test.cat"):
os.rename("test.cat",fname+".cat")
return pixel_catalog(fname+".cat")

View File

208
stvid/astrometry.py 100644
View File

@ -0,0 +1,208 @@
#!/usr/bin/env python
from __future__ import print_function
import os
import numpy as np
import astropy.units as u
from astropy.io import fits
from astropy import wcs
from astropy.coordinates import SkyCoord, FK5, ICRS
from astropy.time import Time
from scipy import optimize
# Class for the Tycho 2 catalog
class tycho2_catalog:
"""Tycho2 catalog"""
def __init__(self, maxmag=9.0):
hdu = fits.open(os.path.join(os.getenv("ST_DATADIR"),
"data/tyc2.fits"))
ra = hdu[1].data.field('RA')*u.deg
dec = hdu[1].data.field('DEC')*u.deg
mag = hdu[1].data.field('MAG_VT')
c = mag < maxmag
self.ra = ra[c]
self.dec = dec[c]
self.mag = mag[c]
# Estimate the WCS from a reference file
def estimate_wcs_from_reference(ref, fname):
# Read header of reference
hdu = fits.open(ref)
hdu[0].header["NAXIS"] = 2
w = wcs.WCS(hdu[0].header)
# Get time and position from reference
tref = Time(hdu[0].header["MJD-OBS"], format="mjd", scale="utc")
pref = SkyCoord(ra=w.wcs.crval[0],
dec=w.wcs.crval[1],
unit="deg",
frame="icrs").transform_to(FK5(equinox=tref))
# Read time from target
hdu = fits.open(fname)
t = Time(hdu[0].header["MJD-OBS"], format="mjd", scale="utc")
# Correct wcs
dra = (t.sidereal_time("mean", "greenwich")
- tref.sidereal_time("mean", "greenwich"))
p = FK5(ra=pref.ra+dra, dec=pref.dec, equinox=t).transform_to(ICRS)
w.wcs.crval = np.array([p.ra.degree, p.dec.degree])
return w
# Match the astrometry and pixel catalog
def match_catalogs(ast_catalog, pix_catalog, w, rmin):
# Select stars towards pointing center
ra, dec = w.wcs.crval*u.deg
d = np.arccos(np.sin(dec)
* np.sin(ast_catalog.dec)
+ np.cos(dec)
* np.cos(ast_catalog.dec)
* np.cos(ra-ast_catalog.ra))
c = (d < 30.0*u.deg)
ra, dec, mag = ast_catalog.ra[c], ast_catalog.dec[c], ast_catalog.mag[c]
# Convert RA/Dec to pixels
pix = w.wcs_world2pix(np.stack((ra, dec), axis=-1), 0)
xs, ys = pix[:, 0], pix[:, 1]
# Loop over stars
nmatch = 0
for i in range(len(pix_catalog.x)):
dx = xs-pix_catalog.x[i]
dy = ys-pix_catalog.y[i]
r = np.sqrt(dx*dx+dy*dy)
if np.min(r) < rmin:
j = np.argmin(r)
pix_catalog.ra[i] = ra[j].value
pix_catalog.dec[i] = dec[j].value
pix_catalog.imag[i] = mag[j]
pix_catalog.flag[i] = 1
nmatch += 1
return nmatch
# Residual function
def residual(a, x, y, z):
return z-(a[0]+a[1]*x+a[2]*y)
# Fit transformation
def fit_wcs(w, pix_catalog):
x0, y0 = w.wcs.crpix
ra0, dec0 = w.wcs.crval
dx, dy = pix_catalog.x-x0, pix_catalog.y-y0
# Iterate to remove outliers
nstars = np.sum(pix_catalog.flag == 1)
for j in range(10):
w = wcs.WCS(naxis=2)
w.wcs.crpix = np.array([0.0, 0.0])
w.wcs.cd = np.array([[1.0, 0.0], [0.0, 1.0]])
w.wcs.ctype = ["RA---TAN", "DEC--TAN"]
w.wcs.set_pv([(2, 1, 45.0)])
c = pix_catalog.flag == 1
# Iterate to move crval to crpix location
for i in range(5):
w.wcs.crval = np.array([ra0, dec0])
world = np.stack((pix_catalog.ra, pix_catalog.dec), axis=-1)
pix = w.wcs_world2pix(world, 1)
rx, ry = pix[:, 0], pix[:, 1]
ax, cov_q, infodict, mesg, ierr = optimize.leastsq(residual,
[0.0, 0.0, 0.0],
args=(dx[c],
dy[c],
rx[c]),
full_output=1)
ay, cov_q, infodict, mesg, ierr = optimize.leastsq(residual,
[0.0, 0.0, 0.0],
args=(dx[c],
dy[c],
ry[c]),
full_output=1)
ra0, dec0 = w.wcs_pix2world([[ax[0], ay[0]]], 1)[0]
# Compute residuals
drx = ax[0]+ax[1]*dx+ax[2]*dy-rx
dry = ay[0]+ay[1]*dx+ay[2]*dy-ry
dr = np.sqrt(drx*drx+dry*dry)
rms = np.sqrt(np.sum(dr[c]**2)/len(dr[c]))
dr[~c] = 1.0
c = (dr < 2.0*rms)
pix_catalog.flag[~c] = 0
# Break if converged
if np.sum(c) == nstars:
break
nstars = np.sum(c)
# Compute residuals
rmsx = np.sqrt(np.sum(drx[c]**2)/len(drx[c]))
rmsy = np.sqrt(np.sum(dry[c]**2)/len(dry[c]))
# Store header
w = wcs.WCS(naxis=2)
w.wcs.crpix = np.array([x0, y0])
w.wcs.crval = np.array([ra0, dec0])
w.wcs.cd = np.array([[ax[1], ax[2]], [ay[1], ay[2]]])
w.wcs.ctype = ["RA---TAN", "DEC--TAN"]
w.wcs.set_pv([(2, 1, 45.0)])
return w, rmsx, rmsy, rms
def add_wcs(fname, w, rmsx, rmsy):
# Read fits
hdu = fits.open(fname)
whdr = {"CRPIX1": w.wcs.crpix[0], "CRPIX2": w.wcs.crpix[1],
"CRVAL1": w.wcs.crval[0], "CRVAL2": w.wcs.crval[1],
"CD1_1": w.wcs.cd[0, 0], "CD1_2": w.wcs.cd[0, 1],
"CD2_1": w.wcs.cd[1, 0], "CD2_2": w.wcs.cd[1, 1],
"CTYPE1": "RA---TAN", "CTYPE2": "DEC--TAN", "CUNIT1": "DEG",
"CUNIT2": "DEG", "CRRES1": rmsx, "CRRES2": rmsy}
# Add keywords
hdr = hdu[0].header
for k, v in whdr.items():
hdr[k] = v
hdu = fits.PrimaryHDU(header=hdr, data=hdu[0].data)
hdu.writeto(fname, overwrite=True, output_verify="ignore")
return
def calibrate_from_reference(fname, ref, pix_catalog):
# Estimated WCS
w = estimate_wcs_from_reference(ref, fname)
# Default rms values
rmsx = 0.0
rmsy = 0.0
# Read catalogs
if (pix_catalog.nstars > 4):
ast_catalog = tycho2_catalog(10.0)
# Match catalogs
nmatch = match_catalogs(ast_catalog, pix_catalog, w, 10.0)
# Fit transformation
if nmatch > 4:
w, rmsx, rmsy, rms = fit_wcs(w, pix_catalog)
# Add wcs
add_wcs(fname, w, rmsx, rmsy)
return w, rmsx, rmsy

50
stvid/stars.py 100644
View File

@ -0,0 +1,50 @@
#!/usr/bin/env python
from __future__ import print_function
import os
import subprocess
import numpy as np
class pixel_catalog:
"""Pixel catalog"""
def __init__(self, fname):
d = np.loadtxt(fname)
if len(d.shape) == 2:
self.x = d[:, 0]
self.y = d[:, 1]
self.mag = d[:, 2]
self.ra = np.empty_like(self.x)
self.dec = np.empty_like(self.x)
self.imag = np.empty_like(self.x)
self.flag = np.zeros_like(self.x)
self.nstars = len(self.mag)
else:
self.x = None
self.y = None
self.mag = None
self.ra = None
self.dec = None
self.imag = None
self.flag = None
self.nstars = 0
def generate_star_catalog(fname):
# Skip if file already exists
if not os.path.exists(fname+".cat"):
# Get sextractor location
env = os.getenv("ST_DATADIR")
# Format command
command = "sextractor %s -c %s/sextractor/default.sex" % (fname, env)
# Run sextractor
output = subprocess.check_output(command, shell=True,
stderr=subprocess.STDOUT)
# Rename file
if os.path.exists("test.cat"):
os.rename("test.cat", fname+".cat")
return pixel_catalog(fname+".cat")