Add calibrate.py for astrometric solving
parent
c8d8256d2a
commit
550399a360
|
@ -205,7 +205,6 @@ if __name__ == '__main__':
|
|||
logging.basicConfig(filename=os.path.join(path, "acquire.log"),
|
||||
level=logging.DEBUG)
|
||||
|
||||
|
||||
# Set location
|
||||
loc = EarthLocation(lat=cfg.getfloat('Common', 'observer_lat')*u.deg,
|
||||
lon=cfg.getfloat('Common', 'observer_lon')*u.deg,
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import configparser
|
||||
import argparse
|
||||
import subprocess
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Read commandline options
|
||||
conf_parser = argparse.ArgumentParser(description='Plate solve FITS file' +
|
||||
' and add WCS on header')
|
||||
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')
|
||||
|
||||
path = args.file_dir
|
||||
extension = 'fits'
|
||||
files = sorted((f for f in os.listdir(path) if f.endswith('.' + extension)),
|
||||
key=lambda x: os.path.getctime(os.path.join(path, x)))
|
||||
|
||||
if files:
|
||||
file_for_astrometry = os.path.join(path, files[0])
|
||||
print("Found " + file_for_astrometry + " for astrometric solving.")
|
||||
|
||||
sex_config = cfg.get('Astrometry', 'sex_config')
|
||||
|
||||
# Format command
|
||||
command = "solve-field -O -y -u app -L 37 -H 40 --use-sextractor " + \
|
||||
"--sextractor-config %s --downsample 2 --x-column X_IMAGE " % sex_config + \
|
||||
"--y-column Y_IMAGE --sort-column MAG_AUTO --sort-ascending " + \
|
||||
"%s" % file_for_astrometry
|
||||
|
||||
# Run sextractor
|
||||
subprocess.run(command, shell=True, stderr=subprocess.STDOUT)
|
||||
|
||||
else:
|
||||
print("No fits file found for astrometric solving.")
|
|
@ -24,3 +24,6 @@ device_id = 0
|
|||
camera_x = 720 # Camera horizontal pixel count
|
||||
camera_y = 576 # Camera vertical pixel count
|
||||
camera_frames = 250 # Camera frames for each image (25fps*10sec=250)
|
||||
|
||||
[Astrometry]
|
||||
sex_config = /path/to/solve.sex
|
||||
|
|
31
imgstat.py
31
imgstat.py
|
@ -1,6 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import numpy as np
|
||||
from astropy.io import ascii
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.dates as mdates
|
||||
|
@ -14,21 +13,30 @@ import os
|
|||
if __name__ == "__main__":
|
||||
# Read commandline options
|
||||
conf_parser = argparse.ArgumentParser(description='Plot image statistics')
|
||||
conf_parser.add_argument("-c", "--conf_file",
|
||||
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",
|
||||
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("-d", "--directory",
|
||||
metavar='FILE',
|
||||
default="./imgstat.csv")
|
||||
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=".")
|
||||
conf_parser.add_argument("-o", "--output",
|
||||
metavar='DIR',
|
||||
dest='file_dir',
|
||||
default=".")
|
||||
conf_parser.add_argument(
|
||||
"-o",
|
||||
"--output",
|
||||
help="Specify output file. Default is 'imgstat.png'",
|
||||
metavar='FILE', default="./imgstat.png")
|
||||
metavar='FILE',
|
||||
default="./imgstat.png")
|
||||
|
||||
args = conf_parser.parse_args()
|
||||
|
||||
|
@ -55,7 +63,10 @@ if __name__ == "__main__":
|
|||
|
||||
pa = pos.transform_to(AltAz(obstime=t, location=loc))
|
||||
|
||||
fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1, figsize=(20, 10), sharex=True)
|
||||
fig, (ax1, ax2, ax3, ax4) = plt.subplots(4,
|
||||
1,
|
||||
figsize=(20, 10),
|
||||
sharex=True)
|
||||
|
||||
date_format = mdates.DateFormatter("%F\n%H:%M:%S")
|
||||
fig.autofmt_xdate(rotation=0, ha="center")
|
||||
|
@ -88,5 +99,3 @@ if __name__ == "__main__":
|
|||
|
||||
plt.tight_layout()
|
||||
plt.savefig(args.output)
|
||||
|
||||
|
||||
|
|
17
keogram.py
17
keogram.py
|
@ -10,6 +10,7 @@ import matplotlib.pyplot as plt
|
|||
import matplotlib.dates as mdates
|
||||
from astropy.time import Time
|
||||
|
||||
|
||||
def generate_keogram(path):
|
||||
# Get files
|
||||
fnames = sorted(glob.glob(os.path.join(path, "processed/2*.fits")))
|
||||
|
@ -42,14 +43,18 @@ if __name__ == "__main__":
|
|||
# Read commandline options
|
||||
conf_parser = argparse.ArgumentParser(description='Process captured' +
|
||||
' video frames.')
|
||||
conf_parser.add_argument("-c", "--conf_file",
|
||||
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",
|
||||
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=".")
|
||||
metavar='DIR',
|
||||
dest='file_dir',
|
||||
default=".")
|
||||
|
||||
args = conf_parser.parse_args()
|
||||
|
||||
|
@ -74,7 +79,11 @@ if __name__ == "__main__":
|
|||
|
||||
# Plot keogram
|
||||
fig, ax = plt.subplots(figsize=(15, 5))
|
||||
ax.imshow(np.log10(keogram), aspect="auto", origin="lower", cmap="magma", extent=[tmin, tmax, 0, 1])
|
||||
ax.imshow(np.log10(keogram),
|
||||
aspect="auto",
|
||||
origin="lower",
|
||||
cmap="magma",
|
||||
extent=[tmin, tmax, 0, 1])
|
||||
|
||||
ax.axes.get_yaxis().set_visible(False)
|
||||
ax.xaxis_date()
|
||||
|
|
32
process.py
32
process.py
|
@ -24,14 +24,18 @@ if __name__ == "__main__":
|
|||
# Read commandline options
|
||||
conf_parser = argparse.ArgumentParser(description='Process captured' +
|
||||
' video frames.')
|
||||
conf_parser.add_argument("-c", "--conf_file",
|
||||
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",
|
||||
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=".")
|
||||
metavar='DIR',
|
||||
dest='file_dir',
|
||||
default=".")
|
||||
|
||||
args = conf_parser.parse_args()
|
||||
|
||||
|
@ -95,8 +99,7 @@ if __name__ == "__main__":
|
|||
pix_catalog = generate_star_catalog(fname)
|
||||
|
||||
# Calibrate astrometry
|
||||
calibrate_from_reference(fname, "test.fits",
|
||||
pix_catalog)
|
||||
calibrate_from_reference(fname, "test.fits", pix_catalog)
|
||||
|
||||
# Generate satellite predictions
|
||||
generate_satellite_predictions(fname)
|
||||
|
@ -105,7 +108,8 @@ if __name__ == "__main__":
|
|||
ids = find_hough3d_lines(fname)
|
||||
|
||||
# Extract tracks
|
||||
extract_tracks(fname, trkrmin, drdtmin, trksig, ntrkmin, results_path)
|
||||
extract_tracks(fname, trkrmin, drdtmin, trksig, ntrkmin,
|
||||
results_path)
|
||||
|
||||
# Stars available and used
|
||||
nused = np.sum(pix_catalog.flag == 1)
|
||||
|
@ -115,16 +119,19 @@ if __name__ == "__main__":
|
|||
ff = fourframe(fname)
|
||||
|
||||
# Write output
|
||||
output = "%s %10.6f %10.6f %4d/%4d %5.1f %5.1f %6.2f +- %6.2f"%(ff.fname, ff.crval[0], ff.crval[1], nused, nstars, 3600.0*ff.crres[0], 3600.0*ff.crres[1], np.mean(ff.zavg), np.std(ff.zavg))
|
||||
output = "%s %10.6f %10.6f %4d/%4d %5.1f %5.1f %6.2f +- %6.2f" % (
|
||||
ff.fname, ff.crval[0], ff.crval[1], nused, nstars,
|
||||
3600.0 * ff.crres[0], 3600.0 * ff.crres[1], np.mean(
|
||||
ff.zavg), np.std(ff.zavg))
|
||||
if is_calibrated(ff):
|
||||
print(colored(output, "green"))
|
||||
else:
|
||||
print(colored(output, "red"))
|
||||
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.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))
|
||||
|
||||
# Move processed files
|
||||
shutil.move(fname, "processed")
|
||||
|
@ -137,4 +144,3 @@ if __name__ == "__main__":
|
|||
|
||||
# Close files
|
||||
fstat.close()
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[flake8]
|
||||
max-complexity = 25
|
||||
max-line-length = 99
|
||||
ignore = F403, W504, E226, W503
|
|
@ -207,6 +207,7 @@ def calibrate_from_reference(fname, ref, pix_catalog):
|
|||
|
||||
return w, rmsx, rmsy
|
||||
|
||||
|
||||
def is_calibrated(ff):
|
||||
if (3600.0*ff.crres[0] < 1e-3) | \
|
||||
(3600.0*ff.crres[1] < 1e-3) | \
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import glob
|
||||
import shutil
|
||||
from stvid.stio import fourframe, satid, observation
|
||||
from stvid.astrometry import is_calibrated
|
||||
|
@ -11,6 +10,7 @@ from scipy import optimize, ndimage
|
|||
from termcolor import colored
|
||||
import datetime
|
||||
|
||||
|
||||
# Gaussian model
|
||||
def model(a, nx, ny):
|
||||
x, y = np.meshgrid(np.arange(nx), np.arange(ny))
|
||||
|
@ -18,12 +18,14 @@ def model(a, nx, ny):
|
|||
arg = -0.5 * (dx**2 + dy**2)
|
||||
return a[3] * np.exp(arg) + a[4]
|
||||
|
||||
|
||||
# Residual function
|
||||
def residual(a, img):
|
||||
ny, nx = img.shape
|
||||
mod = model(a, nx, ny)
|
||||
return (img - mod).ravel()
|
||||
|
||||
|
||||
# Find peak
|
||||
def peakfind(img, w=1.0):
|
||||
# Find approximate location
|
||||
|
@ -51,6 +53,7 @@ def peakfind(img, w=1.0):
|
|||
|
||||
return xc, yc, w, sigma
|
||||
|
||||
|
||||
# Plot selection
|
||||
def plot_selection(id, x0, y0, dt=2.0, w=10.0):
|
||||
dx, dy = id.x1 - id.x0, id.y1 - id.y0
|
||||
|
@ -69,6 +72,7 @@ def plot_selection(id, x0, y0, dt=2.0, w=10.0):
|
|||
|
||||
return
|
||||
|
||||
|
||||
# Check if point is inside selection
|
||||
def inside_selection(ident, tmid, x0, y0, dt=2.0, w=10.0):
|
||||
dx, dy = ident.x1 - ident.x0, ident.y1 - ident.y0
|
||||
|
@ -90,6 +94,7 @@ def inside_selection(ident, tmid, x0, y0, dt=2.0, w=10.0):
|
|||
else:
|
||||
return False
|
||||
|
||||
|
||||
# Get COSPAR ID
|
||||
def get_cospar(norad, nfd):
|
||||
f = open(os.path.join(os.getenv("ST_DATADIR"), "data/desig.txt"))
|
||||
|
@ -105,6 +110,7 @@ def get_cospar(norad, nfd):
|
|||
|
||||
return "%2s %s" % (cospar[0:2], cospar[2:])
|
||||
|
||||
|
||||
# IOD position format 2: RA/DEC = HHMMmmm+DDMMmm MX (MX in minutes of arc)
|
||||
def format_position(ra, de):
|
||||
ram = 60.0 * ra / 15.0
|
||||
|
@ -121,8 +127,9 @@ def format_position(ra, de):
|
|||
else:
|
||||
sign = "+"
|
||||
|
||||
return ("%02d%06.3f%c%02d%05.2f"
|
||||
% (rah, ram, sign, ded, dem)).replace(".", "")
|
||||
return ("%02d%06.3f%c%02d%05.2f" % (rah, ram, sign, ded, dem)).replace(
|
||||
".", "")
|
||||
|
||||
|
||||
# Format IOD line
|
||||
def format_iod_line(norad, cospar, site_id, t, ra, de):
|
||||
|
@ -132,12 +139,10 @@ def format_iod_line(norad, cospar, site_id, t, ra, de):
|
|||
.replace(":", "") \
|
||||
.replace(".", "")
|
||||
|
||||
return "%05d %-9s %04d G %s 17 25 %s 37 S" % (norad,
|
||||
cospar,
|
||||
site_id,
|
||||
tstr,
|
||||
return "%05d %-9s %04d G %s 17 25 %s 37 S" % (norad, cospar, site_id, tstr,
|
||||
pstr)
|
||||
|
||||
|
||||
def store_results(ident, fname, path, iod_line):
|
||||
# Find destination
|
||||
if ident.catalog.find("classfd.tle") > 0:
|
||||
|
@ -167,7 +172,7 @@ def store_results(ident, fname, path, iod_line):
|
|||
shutil.copy2(fname + ".png", dest)
|
||||
try:
|
||||
shutil.move(fname.replace(".fits", "_%05d.png" % ident.norad), dest)
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Write iodline
|
||||
|
@ -177,6 +182,7 @@ def store_results(ident, fname, path, iod_line):
|
|||
|
||||
return
|
||||
|
||||
|
||||
def plot_header(fname, ff, iod_line):
|
||||
# ppgplot arrays
|
||||
heat_l = np.array([0.0, 0.2, 0.4, 0.6, 1.0])
|
||||
|
@ -191,29 +197,21 @@ def plot_header(fname, ff, iod_line):
|
|||
|
||||
ppg.pgsch(0.8)
|
||||
ppg.pgmtxt("T", 6.0, 0.0, 0.0,
|
||||
"UT Date: %.23s COSPAR ID: %04d"
|
||||
% (ff.nfd, ff.site_id))
|
||||
"UT Date: %.23s COSPAR ID: %04d" % (ff.nfd, ff.site_id))
|
||||
if is_calibrated(ff):
|
||||
ppg.pgsci(1)
|
||||
else:
|
||||
ppg.pgsci(2)
|
||||
ppg.pgmtxt("T", 4.8, 0.0, 0.0,
|
||||
"R.A.: %10.5f (%4.1f'') Decl.: %10.5f (%4.1f'')"
|
||||
% (ff.crval[0],
|
||||
3600.0*ff.crres[0],
|
||||
ff.crval[1],
|
||||
3600.0*ff.crres[1]))
|
||||
ppg.pgmtxt(
|
||||
"T", 4.8, 0.0, 0.0, "R.A.: %10.5f (%4.1f'') Decl.: %10.5f (%4.1f'')" %
|
||||
(ff.crval[0], 3600.0 * ff.crres[0], ff.crval[1], 3600.0 * ff.crres[1]))
|
||||
ppg.pgsci(1)
|
||||
ppg.pgmtxt("T", 3.6, 0.0, 0.0,
|
||||
("FoV: %.2f\\(2218)x%.2f\\(2218) "
|
||||
"Scale: %.2f''x%.2f'' pix\\u-1\\d")
|
||||
% (ff.wx, ff.wy, 3600.0*ff.sx, 3600.0*ff.sy))
|
||||
ppg.pgmtxt("T", 2.4, 0.0, 0.0,
|
||||
"Stat: %5.1f+-%.1f (%.1f-%.1f)"
|
||||
% (np.mean(ff.zmax),
|
||||
np.std(ff.zmax),
|
||||
ff.zmaxmin,
|
||||
ff.zmaxmax))
|
||||
ppg.pgmtxt("T", 3.6, 0.0, 0.0, ("FoV: %.2f\\(2218)x%.2f\\(2218) "
|
||||
"Scale: %.2f''x%.2f'' pix\\u-1\\d") %
|
||||
(ff.wx, ff.wy, 3600.0 * ff.sx, 3600.0 * ff.sy))
|
||||
ppg.pgmtxt(
|
||||
"T", 2.4, 0.0, 0.0, "Stat: %5.1f+-%.1f (%.1f-%.1f)" %
|
||||
(np.mean(ff.zmax), np.std(ff.zmax), ff.zmaxmin, ff.zmaxmax))
|
||||
ppg.pgmtxt("T", 0.3, 0.0, 0.0, iod_line)
|
||||
|
||||
ppg.pgsch(1.0)
|
||||
|
@ -277,12 +275,8 @@ def extract_tracks(fname, trkrmin, drdtmin, trksig, ntrkmin, path):
|
|||
continue
|
||||
|
||||
# Extract significant pixels along a track
|
||||
x, y, t, sig = ff.significant_pixels_along_track(trksig,
|
||||
ident.x0,
|
||||
ident.y0,
|
||||
ident.dxdt,
|
||||
ident.dydt,
|
||||
trkrmin)
|
||||
x, y, t, sig = ff.significant_pixels_along_track(
|
||||
trksig, ident.x0, ident.y0, ident.dxdt, ident.dydt, trkrmin)
|
||||
|
||||
# Fit tracks
|
||||
if len(t) > ntrkmin:
|
||||
|
@ -310,18 +304,15 @@ def extract_tracks(fname, trkrmin, drdtmin, trksig, ntrkmin, path):
|
|||
|
||||
cospar = get_cospar(ident.norad, ff.nfd)
|
||||
obs = observation(ff, mjd, x0, y0)
|
||||
iod_line = "%s" % format_iod_line(ident.norad,
|
||||
cospar,
|
||||
ff.site_id,
|
||||
obs.nfd,
|
||||
obs.ra,
|
||||
obs.de)
|
||||
iod_line = "%s" % format_iod_line(ident.norad, cospar, ff.site_id,
|
||||
obs.nfd, obs.ra, obs.de)
|
||||
|
||||
# Create diagnostic plot
|
||||
plot_header(fname.replace(".fits", "_%05d.png/png" % ident.norad), ff, iod_line)
|
||||
plot_header(fname.replace(".fits", "_%05d.png/png" % ident.norad),
|
||||
ff, iod_line)
|
||||
|
||||
ppg.pgimag(ff.zmax, ff.nx, ff.ny, 0, ff.nx-1,
|
||||
0, ff.ny-1, ff.zmaxmax, ff.zmaxmin, tr)
|
||||
ppg.pgimag(ff.zmax, ff.nx, ff.ny, 0, ff.nx - 1, 0, ff.ny - 1,
|
||||
ff.zmaxmax, ff.zmaxmin, tr)
|
||||
ppg.pgbox("BCTSNI", 0., 0, "BCTSNI", 0., 0)
|
||||
ppg.pgstbg(1)
|
||||
|
||||
|
@ -359,8 +350,8 @@ def extract_tracks(fname, trkrmin, drdtmin, trksig, ntrkmin, path):
|
|||
mjd = ff.mjd + tmid / 86400.0
|
||||
xmid = ident.x0 + ident.dxdt * tmid
|
||||
ymid = ident.y0 + ident.dydt * tmid
|
||||
ztrk = ndimage.gaussian_filter(ff.track(ident.dxdt, ident.dydt, tmid),
|
||||
1.0)
|
||||
ztrk = ndimage.gaussian_filter(
|
||||
ff.track(ident.dxdt, ident.dydt, tmid), 1.0)
|
||||
vmin = np.mean(ztrk) - 2.0 * np.std(ztrk)
|
||||
vmax = np.mean(ztrk) + 6.0 * np.std(ztrk)
|
||||
|
||||
|
@ -394,20 +385,15 @@ def extract_tracks(fname, trkrmin, drdtmin, trksig, ntrkmin, path):
|
|||
# Format IOD line
|
||||
cospar = get_cospar(ident.norad, ff.nfd)
|
||||
obs = observation(ff, mjd, x0, y0)
|
||||
iod_line = "%s" % format_iod_line(ident.norad,
|
||||
cospar,
|
||||
ff.site_id,
|
||||
obs.nfd,
|
||||
obs.ra,
|
||||
obs.de)
|
||||
|
||||
iod_line = "%s" % format_iod_line(ident.norad, cospar, ff.site_id,
|
||||
obs.nfd, obs.ra, obs.de)
|
||||
|
||||
# Create diagnostic plot
|
||||
plot_header(fname.replace(".fits", "_%05d.png/png" % ident.norad), ff, iod_line)
|
||||
plot_header(fname.replace(".fits", "_%05d.png/png" % ident.norad),
|
||||
ff, iod_line)
|
||||
|
||||
|
||||
ppg.pgimag(ztrk, ff.nx, ff.ny, 0, ff.nx-1,
|
||||
0, ff.ny-1, vmax, vmin, tr)
|
||||
ppg.pgimag(ztrk, ff.nx, ff.ny, 0, ff.nx - 1, 0, ff.ny - 1, vmax,
|
||||
vmin, tr)
|
||||
ppg.pgbox("BCTSNI", 0., 0, "BCTSNI", 0., 0)
|
||||
ppg.pgstbg(1)
|
||||
|
||||
|
@ -423,8 +409,7 @@ def extract_tracks(fname, trkrmin, drdtmin, trksig, ntrkmin, path):
|
|||
ppg.pgdraw(ident.x1, ident.y1)
|
||||
ppg.pgpt(np.array([x0]), np.array([y0]), 4)
|
||||
ppg.pgsch(0.65)
|
||||
ppg.pgtext(np.array([ident.x0]),
|
||||
np.array([ident.y0]),
|
||||
ppg.pgtext(np.array([ident.x0]), np.array([ident.y0]),
|
||||
" %05d" % ident.norad)
|
||||
ppg.pgsch(1.0)
|
||||
ppg.pgsci(1)
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
from stvid.stio import fourframe
|
||||
from stvid.stio import satid
|
||||
from stvid.stio import observation
|
||||
|
||||
|
||||
def generate_satellite_predictions(fname):
|
||||
# Format command
|
||||
command = "satid %s %s.png/png" % (fname, fname)
|
||||
|
||||
# Run command
|
||||
output = subprocess.check_output(command, shell=True,
|
||||
output = subprocess.check_output(command,
|
||||
shell=True,
|
||||
stderr=subprocess.STDOUT)
|
||||
|
||||
return output
|
||||
|
@ -38,12 +38,13 @@ def find_hough3d_lines(fname, ntrkmin=20, dr=8):
|
|||
f.close()
|
||||
|
||||
# Run 3D Hough line-finding algorithm
|
||||
command = "hough3dlines -dx %d -minvotes %d %s" % (dr, ntrkmin, "/tmp/hough.dat")
|
||||
command = "hough3dlines -dx %d -minvotes %d %s" % (dr, ntrkmin,
|
||||
"/tmp/hough.dat")
|
||||
try:
|
||||
output = subprocess.check_output(command,
|
||||
shell=True,
|
||||
stderr=subprocess.STDOUT)
|
||||
except:
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
# Clean output (a bit cluncky)
|
||||
|
@ -58,8 +59,10 @@ def find_hough3d_lines(fname, ntrkmin=20, dr=8):
|
|||
s = cleaned_output.split()
|
||||
for i in range(len(s) // 7):
|
||||
# Extract points
|
||||
x0, y0, z0 = float(s[1+7*i]), float(s[2+7*i]), float(s[3+7*i])
|
||||
dx, dy, dz = float(s[4+7*i]), float(s[5+7*i]), float(s[6+7*i])
|
||||
x0, y0, z0 = float(s[1 + 7 * i]), float(s[2 + 7 * i]), float(s[3 +
|
||||
7 * i])
|
||||
dx, dy, dz = float(s[4 + 7 * i]), float(s[5 + 7 * i]), float(s[6 +
|
||||
7 * i])
|
||||
|
||||
# Reconstruct start and end points
|
||||
xmin = x0 - z0 * dx / (dz + 1e-9)
|
||||
|
|
|
@ -22,7 +22,9 @@ class observation:
|
|||
self.nfd = Time(self.mjd, format='mjd', scale='utc').isot
|
||||
|
||||
# Correct for rotation
|
||||
tobs = Time(ff.mjd+0.5*ff.texp/86400.0, format='mjd', scale='utc')
|
||||
tobs = Time(ff.mjd + 0.5 * ff.texp / 86400.0,
|
||||
format='mjd',
|
||||
scale='utc')
|
||||
tobs.delta_ut1_utc = 0
|
||||
hobs = tobs.sidereal_time("mean", longitude=0.0).degree
|
||||
tmid = Time(self.mjd, format='mjd', scale='utc')
|
||||
|
@ -54,11 +56,9 @@ class satid:
|
|||
self.dydt = (self.y1 - self.y0) / (self.t1 - self.t0)
|
||||
|
||||
def __repr__(self):
|
||||
return "%s %f %f %f -> %f %f %f %d %s %s" % (self.nfd, self.x0,
|
||||
self.y0, self.t0,
|
||||
self.x1, self.y1,
|
||||
self.t1, self.norad,
|
||||
self.catalog, self.state)
|
||||
return "%s %f %f %f -> %f %f %f %d %s %s" % (
|
||||
self.nfd, self.x0, self.y0, self.t0, self.x1, self.y1, self.t1,
|
||||
self.norad, self.catalog, self.state)
|
||||
|
||||
|
||||
class fourframe:
|
||||
|
@ -102,8 +102,8 @@ class fourframe:
|
|||
self.nz = hdu[0].header['NFRAMES']
|
||||
|
||||
# Read frame time oselfsets
|
||||
self.dt = np.array([hdu[0].header['DT%04d' % i]
|
||||
for i in range(self.nz)])
|
||||
self.dt = np.array(
|
||||
[hdu[0].header['DT%04d' % i] for i in range(self.nz)])
|
||||
|
||||
# Read header
|
||||
self.mjd = hdu[0].header['MJD-OBS']
|
||||
|
@ -114,18 +114,17 @@ class fourframe:
|
|||
self.fname = fname
|
||||
|
||||
# Astrometry keywords
|
||||
self.crpix = np.array([hdu[0].header['CRPIX1'],
|
||||
hdu[0].header['CRPIX2']])
|
||||
self.crval = np.array([hdu[0].header['CRVAL1'],
|
||||
hdu[0].header['CRVAL2']])
|
||||
self.cd = np.array([[hdu[0].header['CD1_1'],
|
||||
hdu[0].header['CD1_2']],
|
||||
[hdu[0].header['CD2_1'],
|
||||
hdu[0].header['CD2_2']]])
|
||||
self.crpix = np.array(
|
||||
[hdu[0].header['CRPIX1'], hdu[0].header['CRPIX2']])
|
||||
self.crval = np.array(
|
||||
[hdu[0].header['CRVAL1'], hdu[0].header['CRVAL2']])
|
||||
self.cd = np.array(
|
||||
[[hdu[0].header['CD1_1'], hdu[0].header['CD1_2']],
|
||||
[hdu[0].header['CD2_1'], hdu[0].header['CD2_2']]])
|
||||
self.ctype = [hdu[0].header['CTYPE1'], hdu[0].header['CTYPE2']]
|
||||
self.cunit = [hdu[0].header['CUNIT1'], hdu[0].header['CUNIT2']]
|
||||
self.crres = np.array([hdu[0].header['CRRES1'],
|
||||
hdu[0].header['CRRES2']])
|
||||
self.crres = np.array(
|
||||
[hdu[0].header['CRRES1'], hdu[0].header['CRRES2']])
|
||||
|
||||
hdu.close()
|
||||
|
||||
|
@ -189,8 +188,13 @@ class fourframe:
|
|||
|
||||
return x, y, inum, t, sig
|
||||
|
||||
def significant_pixels_along_track(self, sigma, x0, y0,
|
||||
dxdt, dydt, rmin=10.0):
|
||||
def significant_pixels_along_track(self,
|
||||
sigma,
|
||||
x0,
|
||||
y0,
|
||||
dxdt,
|
||||
dydt,
|
||||
rmin=10.0):
|
||||
"""Extract significant pixels along a track"""
|
||||
|
||||
# Generate sigma frame
|
||||
|
@ -267,11 +271,6 @@ class fourframe:
|
|||
return ztrk
|
||||
|
||||
def __repr__(self):
|
||||
return "%s %dx%dx%d %s %.3f %d %s" % (self.fname,
|
||||
self.nx,
|
||||
self.ny,
|
||||
self.nz,
|
||||
self.nfd,
|
||||
self.texp,
|
||||
self.site_id,
|
||||
self.observer)
|
||||
return "%s %dx%dx%d %s %.3f %d %s" % (self.fname, self.nx, self.ny,
|
||||
self.nz, self.nfd, self.texp,
|
||||
self.site_id, self.observer)
|
||||
|
|
|
@ -28,8 +28,10 @@ def get_sunset_and_sunrise(tnow, loc, refalt_set, refalt_rise):
|
|||
|
||||
# Compute altitude extrema
|
||||
de = np.mean(pos.dec)
|
||||
minalt = np.arcsin(np.sin(loc.lat)*np.sin(de)-np.cos(loc.lat)*np.cos(de))
|
||||
maxalt = np.arcsin(np.sin(loc.lat)*np.sin(de)+np.cos(loc.lat)*np.cos(de))
|
||||
minalt = np.arcsin(
|
||||
np.sin(loc.lat) * np.sin(de) - np.cos(loc.lat) * np.cos(de))
|
||||
maxalt = np.arcsin(
|
||||
np.sin(loc.lat) * np.sin(de) + np.cos(loc.lat) * np.cos(de))
|
||||
|
||||
# Never sets, never rises?
|
||||
if minalt > min(refalt_set, refalt_rise):
|
||||
|
@ -49,12 +51,12 @@ def get_sunset_and_sunrise(tnow, loc, refalt_set, refalt_rise):
|
|||
fde = interpolate.interp1d(t.mjd, pos.dec.degree)
|
||||
|
||||
# Get GMST
|
||||
gmst0 = Time(mjd0,
|
||||
format='mjd',
|
||||
gmst0 = Time(mjd0, format='mjd',
|
||||
scale='utc').sidereal_time('mean', 'greenwich')
|
||||
|
||||
# Get transit time
|
||||
mtransit = np.mod((fra(mjd0)*u.degree-loc.lon-gmst0)/(360.0*u.degree), 1.0)
|
||||
mtransit = np.mod(
|
||||
(fra(mjd0) * u.degree - loc.lon - gmst0) / (360.0 * u.degree), 1.0)
|
||||
while True:
|
||||
gmst = gmst0 + 360.985647 * u.deg * mtransit
|
||||
ra = fra(mjd0 + mtransit) * u.deg
|
||||
|
@ -64,11 +66,9 @@ def get_sunset_and_sunrise(tnow, loc, refalt_set, refalt_rise):
|
|||
break
|
||||
|
||||
# Hour angle offset
|
||||
ha0 = np.arccos((np.sin(refalt_set)
|
||||
- np.sin(loc.lat)
|
||||
* np.sin(np.mean(pos.dec)))
|
||||
/ (np.cos(loc.lat)
|
||||
* np.cos(np.mean(pos.dec))))
|
||||
ha0 = np.arccos(
|
||||
(np.sin(refalt_set) - np.sin(loc.lat) * np.sin(np.mean(pos.dec))) /
|
||||
(np.cos(loc.lat) * np.cos(np.mean(pos.dec))))
|
||||
|
||||
# Get set time
|
||||
mset = mtransit + ha0 / (360.0 * u.deg)
|
||||
|
@ -77,16 +77,11 @@ def get_sunset_and_sunrise(tnow, loc, refalt_set, refalt_rise):
|
|||
ra = fra(mjd0 + mset) * u.deg
|
||||
de = fde(mjd0 + mset) * u.deg
|
||||
ha = gmst + loc.lon - ra
|
||||
alt = np.arcsin(np.sin(loc.lat)
|
||||
* np.sin(de)
|
||||
+ np.cos(loc.lat)
|
||||
* np.cos(de)
|
||||
* np.cos(ha))
|
||||
dm = (alt-refalt_set)/(360.0
|
||||
* u.deg
|
||||
* np.cos(de)
|
||||
* np.cos(loc.lat)
|
||||
* np.sin(ha))
|
||||
alt = np.arcsin(
|
||||
np.sin(loc.lat) * np.sin(de) +
|
||||
np.cos(loc.lat) * np.cos(de) * np.cos(ha))
|
||||
dm = (alt - refalt_set) / (360.0 * u.deg * np.cos(de) *
|
||||
np.cos(loc.lat) * np.sin(ha))
|
||||
mset += dm
|
||||
|
||||
# Break loop or find sunset on next day
|
||||
|
@ -106,16 +101,11 @@ def get_sunset_and_sunrise(tnow, loc, refalt_set, refalt_rise):
|
|||
ra = fra(mjd0 + mrise) * u.deg
|
||||
de = fde(mjd0 + mrise) * u.deg
|
||||
ha = gmst + loc.lon - ra
|
||||
alt = np.arcsin(np.sin(loc.lat)
|
||||
* np.sin(de)
|
||||
+ np.cos(loc.lat)
|
||||
* np.cos(de)
|
||||
* np.cos(ha))
|
||||
dm = (alt-refalt_rise)/(360.0
|
||||
* u.deg
|
||||
* np.cos(de)
|
||||
* np.cos(loc.lat)
|
||||
* np.sin(ha))
|
||||
alt = np.arcsin(
|
||||
np.sin(loc.lat) * np.sin(de) +
|
||||
np.cos(loc.lat) * np.cos(de) * np.cos(ha))
|
||||
dm = (alt - refalt_rise) / (360.0 * u.deg * np.cos(de) *
|
||||
np.cos(loc.lat) * np.sin(ha))
|
||||
mrise += dm
|
||||
|
||||
# Break loop or find sunrise on next day
|
||||
|
|
|
@ -3,7 +3,6 @@ from __future__ import print_function
|
|||
import configparser
|
||||
import argparse
|
||||
from spacetrack import SpaceTrackClient
|
||||
import subprocess
|
||||
from shutil import copyfile
|
||||
import datetime
|
||||
from io import BytesIO
|
||||
|
|
Loading…
Reference in New Issue