more apps

This commit is contained in:
2024-04-26 12:43:00 +03:00
parent 52b209b176
commit 69a2160eb7
536 changed files with 33118 additions and 0 deletions

0
monthplan/__init__.py Normal file
View File

15
monthplan/admin.py Normal file
View File

@@ -0,0 +1,15 @@
from django.contrib import admin
from monthplan.models import Head, Observation, Seance, Correction, Scan, Survey, MonthPlanUpload, FlightPlan, DataDump, SurveyHealpixPlate
# Register your models here.
admin.site.register(Head)
admin.site.register(Observation)
admin.site.register(Seance)
admin.site.register(Correction)
admin.site.register(Scan)
admin.site.register(Survey)
admin.site.register(MonthPlanUpload)
admin.site.register(FlightPlan)
admin.site.register(DataDump)
admin.site.register(SurveyHealpixPlate)
#admin.site.register(ScanPath)

5
monthplan/apps.py Normal file
View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class MonthplanConfig(AppConfig):
name = 'monthplan'

4
monthplan/forms.py Normal file
View File

@@ -0,0 +1,4 @@
from django import forms
class ObsIDSearchForm(forms.Form):
obsid = forms.CharField(label='obsid', max_length=11)

View File

@@ -0,0 +1,29 @@
from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth.models import User
from django.core import mail
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.core.mail import send_mail
import time
import re
import glob
import logging
from monthplan.utils import load_surveypath_data
class Command(BaseCommand):
help = 'Initiates data base'
def handle(self, *args, **options):
logging.getLogger().setLevel(logging.INFO)
path = "/export/django/srg/data/npol/DMV/ARJ-SCAN/20??????_??????_???????????.iki"
ikifiles = []
for file in glob.glob(path):
ikifiles.append(file)
for file in ikifiles:
load_surveypath_data(file,100,notify=True)

View File

@@ -0,0 +1,76 @@
from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth.models import User
from django.core import mail
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.core.mail import send_mail
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from watchdog.events import PatternMatchingEventHandler
class MyHandler(PatternMatchingEventHandler):
patterns = ["*gyro.fits",]
def process(self, event):
"""
event.event_type
'modified' | 'created' | 'moved' | 'deleted'
event.is_directory
True | False
event.src_path
path/to/observed/file
"""
# the file will be processed there
if not event.event_type == 'created':
return
print("Reading {} ty[e: {}".format(event.src_path, event.event_type))
#if not 'L1b' in event.src_path:
# return
users = User.objects.filter(groups__name='srg-artxc-survey')
to_emails=[]
for user in users:
to_emails.append(user.email)
print (event.src_path, event.event_type) # print now only for degug
count=1
subject = "New SRG data"
html_message = render_to_string('monthplan/data_loaded_email.html', {'event':event, 'count':count})
plain_message = strip_tags(html_message)
from_email = 'Roman Krivonos <krivonos@cosmos.ru>'
mail.send_mail(subject, plain_message, from_email, ['krivonos@cosmos.ru','kate@cosmos.ru',], html_message=html_message)
def on_modified(self, event):
self.process(event)
def on_created(self, event):
self.process(event)
class EventHandler(FileSystemEventHandler):
def on_created(self, event):
print (event)
class Command(BaseCommand):
help = 'Initiates data base'
def handle(self, *args, **options):
path = "/srg/work/oper/data/2020/"
observer = Observer()
observer.schedule(MyHandler(), path, recursive=True)
observer.start()
try:
while True:
time.sleep(10)
except KeyboardInterrupt:
observer.stop()
observer.join()

View File

@@ -0,0 +1,19 @@
from django.core.management.base import BaseCommand, CommandError
from datetime import date
from logbook.models import LogBookDay
from plan.models import INPUT_DATA_DIR
from plan.models import LaunchDate
import datetime
from django.utils import timezone
import astropy
import pandas as pd
class Command(BaseCommand):
help = 'Initiates data dase'
# def add_arguments(self, parser):
# parser.add_argument('poll_id', nargs='+', type=int)
def handle(self, *args, **options):
self.stdout.write(self.style.SUCCESS('Successfully initiated "%s"' % 100))

View File

@@ -0,0 +1,123 @@
from django.core.management.base import BaseCommand, CommandError
from datetime import date
from django.utils import dateparse
from logbook.models import LogBookPlan, LogBookDay
from plan.models import INPUT_DATA_DIR
from plan.models import LaunchDate
from monthplan.models import Head, Observation, Seance, Correction, Scan, Survey
from monthplan.utils import load_monthplan_fits, load_monthplan_dir
from astropy.io import fits
import datetime
from django.utils import timezone
from astropy.io import fits
import pandas as pd
from pandas import ExcelWriter
from pandas import ExcelFile
#import xlrd
from astropy.table import Table
import math
def load_data(file):
print('Load data (dummy)')
fitsfile=INPUT_DATA_DIR+'/'+file
table = Table.read(fitsfile)
df = table.to_pandas()
print("Column headings:")
print(df.columns.str.encode('utf-8'))
hdul = fits.open(fitsfile)
hdul.info()
head=Head()
head.start=hdul[1].header['START']
head.stop=hdul[1].header['STOP']
head.gentime=hdul[1].header['GENTIME']
head.version=hdul[1].header['VERSION']
head.author=hdul[1].header['AUTHOR']
head.file=file
head.nrows=df.shape[0]
head.save()
for i in df.index:
row=(i+1)
if(df['TYPE'][i].decode().strip() == 'SEANCE'):
print('SEA')
print(df['START'][i].decode().strip())
seance=Seance(head=head, row=row)
seance.start=df['START'][i].decode().strip()
seance.stop=df['STOP'][i].decode().strip()
seance.stations=df['STATIONS'][i].decode().strip()
seance.guid=df['GUID'][i].decode().strip()
seance.save()
if(df['TYPE'][i].decode().strip() == 'OBSERVATION'):
obs=Observation(head=head, row=row)
obs.start=df['START'][i].decode().strip()
obs.stop=df['STOP'][i].decode().strip()
obs.target=df['TARGET'][i].decode().strip()
obs.experiment=df['EXPERIMENT'][i].decode().strip()
obs.ra=df['RA'][i]
obs.dec=df['DEC'][i]
obs.ra=df['RA'][i]
obs.roll_angle=df['ROLL_ANGLE'][i]
obs.sun_xoz_angle=df['SUN_XOZ_ANGLE'][i]
obs.guid=df['GUID'][i].decode().strip()
obs.save()
if(df['TYPE'][i].decode().strip() == 'CORRECTION'):
cor=Correction(head=head, row=row)
cor.start=df['START'][i].decode().strip()
cor.stop=df['STOP'][i].decode().strip()
cor.impstart=df['IMPSTART'][i].decode().strip()
cor.guid=df['GUID'][i].decode().strip()
cor.save()
if(df['TYPE'][i].decode().strip() == 'SCAN'):
print('SCAN')
scan=Scan(head=head, row=row)
scan.start=df['START'][i].decode().strip()
scan.stop=df['STOP'][i].decode().strip()
scan.target=df['TARGET'][i].decode().strip()
scan.experiment=df['EXPERIMENT'][i].decode().strip()
scan.ra=df['RA'][i]
scan.dec=df['DEC'][i]
scan.roll_angle=df['ROLL_ANGLE'][i]
scan.sun_xoz_angle=df['SUN_XOZ_ANGLE'][i]
scan.template=int(df['TEMPLATE'][i].decode().strip())
scan.guid=df['GUID'][i].decode().strip()
scan.save()
if(df['TYPE'][i].decode().strip() == 'SURVEY'):
sur=Scan(head=head, row=row)
sur.start=df['START'][i].decode().strip()
sur.stop=df['STOP'][i].decode().strip()
sur.target=df['TARGET'][i].decode().strip()
sur.experiment=df['EXPERIMENT'][i].decode().strip()
sur.ra_p=df['RA_P'][i]
sur.dec_p=df['DEC_P'][i]
sur.ra_z0=df['RA_Z0'][i]
sur.dec_z0=df['DEC_Z0'][i]
sur.ra_zk=df['RA_ZK'][i]
sur.dec_zk=df['DEC_ZK'][i]
sur.z_speed=df['Z_SPEED'][i]
sur.guid=df['GUID'][i].decode().strip()
sur.save()
#myplan = LogBookPlan(daynumber=myday.daynumber, description=df['plan'][i], date=df['date'][i])
#myplan.save()
#myday.plan.add(myplan)
#myday.save()
print(df['TYPE'][i])
pass
class Command(BaseCommand):
help = 'Initiates data base'
# def add_arguments(self, parser):
# parser.add_argument('poll_id', nargs='+', type=int)
def handle(self, *args, **options):
#load_data('RG_MonthPlan_2019-07_v08.fits')
#load_data('RG_MonthPlan_2019-08_v14.fits')
#load_monthplan_fits('/export/django/srg/data/npol/fits/RG_MonthPlan_2020-06_v07.fits')
load_monthplan_dir('/export/django/srg/data/npol/fits')
self.stdout.write(self.style.SUCCESS("Done"))

View File

@@ -0,0 +1,127 @@
from django.core.management.base import BaseCommand, CommandError
from datetime import date
from django.utils import dateparse
from logbook.models import LogBookPlan, LogBookDay
from plan.models import INPUT_DATA_DIR
from plan.models import LaunchDate
from monthplan.models import Head, Observation, Seance, Correction, Scan, Survey, FlightPlan
from astropy.io import fits
from django.utils import timezone
from astropy.io import fits
import pandas as pd
from pandas import ExcelWriter
from pandas import ExcelFile
#import xlrd
from astropy.table import Table
import math
import astropy.units as u
from astropy.time.formats import erfa
from astropy.time import Time, TimeDelta, TimezoneInfo, TimeFromEpoch
from datetime import datetime
MJDREF = 51543.875
TZ_UTC = TimezoneInfo(utc_offset=0*u.hour)
TZ_MSK = TimezoneInfo(utc_offset=3*u.hour)
# 2019-08-01T02:28:00+03:00
TIMESTR_FORMAT = '%Y-%m-%dT%H:%M:%S+03:00'
def str2date(timestr, tzone):
time_raw = datetime.strptime(timestr, TIMESTR_FORMAT)
time_zoned = time_raw.replace(tzinfo=tzone)
return time_zoned
def date2mission(dtime):
mjdref = Time(MJDREF, format='mjd')
dtime = Time(dtime , format='datetime')
return (dtime - mjdref).sec
def mission2date(timesec, tzone):
mjdref = Time(MJDREF, format='mjd')
delta = TimeDelta(timesec, format='sec')
dtime = mjdref + delta + 3*u.hour
return dtime.to_datetime()
def print_obsplan_dt_sec(dtstr):
dt = str2date(dtstr, tzone=TZ_MSK)
ts = date2mission(dt)
print(dt, '-->', ts)
def print_pz_dt_sec(dtstr):
dt = str2date(dtstr, tzone=TZ_UTC)
ts = date2mission(dt)
print(dt, '-->', ts)
def load_data(file):
print('Load data (dummy)')
fitsfile=INPUT_DATA_DIR+'/'+file
table = Table.read(fitsfile)
df = table.to_pandas()
print("Column headings:")
print(df.columns.str.encode('utf-8'))
hdul = fits.open(fitsfile)
hdul.info()
for i in df.index:
dtstr=df['START'][i].decode().strip()
dt = str2date(dtstr, tzone=TZ_MSK)
start_ts = date2mission(dt)
dtstr=df['STOP'][i].decode().strip()
dt = str2date(dtstr, tzone=TZ_MSK)
stop_ts = date2mission(dt)
#print(dt, '-->', ts)
obs=FlightPlan()
obs.start=df['START'][i].decode().strip()
obs.stop=df['STOP'][i].decode().strip()
obs.experiment=df['EXPERIMENT'][i].decode().strip()
obs.ra=df['RA'][i]
obs.dec=df['DEC'][i]
obs.q1=df['Q1'][i]
obs.q2=df['Q2'][i]
obs.q3=df['Q3'][i]
obs.q4=df['Q4'][i]
obs.start_npol = df['START_NPOL'][i].decode().strip()
obs.stop_npol = df['STOP_NPOL'][i].decode().strip()
obs.load_stamp = df['LOAD_STAMP'][i].decode().strip()
obs.mjd_start = df['MJD_START'][i]
obs.mjd_stop = df['MJD_STOP'][i]
obs.obt_start = start_ts # df['OBT_START'][i]
obs.obt_stop = stop_ts # df['OBT_STOP'][i]
obs.save()
print(df['EXPERIMENT'][i])
pass
def validate_flightplan():
list = FlightPlan.objects.all()
for pz in list:
if (pz.experiment == '00000000000' and pz.valid == True):
pz.valid = False
pz.save()
continue
first = FlightPlan.objects.filter(experiment__exact=pz.experiment).order_by("-load_stamp")[0]
first.valid = True
first.save()
pass
class Command(BaseCommand):
help = 'Initiates data base'
# def add_arguments(self, parser):
# parser.add_argument('poll_id', nargs='+', type=int)
def handle(self, *args, **options):
pz = FlightPlan.objects.all()
pz.delete()
load_data('pz.fits')
validate_flightplan()

View File

@@ -0,0 +1,126 @@
from django.core.management.base import BaseCommand, CommandError
from datetime import date
from django.utils import dateparse
from logbook.models import LogBookPlan, LogBookDay
from plan.models import INPUT_DATA_DIR
from plan.models import LaunchDate
from monthplan.models import Head, Observation, Seance, Correction, Scan, Survey, FlightPlan, DataDump
from astropy.io import fits
from datetime import datetime
from django.utils import timezone
from astropy.io import fits
import pandas as pd
from pandas import ExcelWriter
from pandas import ExcelFile
import xlrd
from astropy.table import Table
import astropy.units as u
from astropy.time.formats import erfa
from astropy.time import Time, TimeDelta, TimezoneInfo, TimeFromEpoch
from django.db.models import Q
import math
MJDREF = 51543.875
TZ_UTC = TimezoneInfo(utc_offset=0*u.hour)
TZ_MSK = TimezoneInfo(utc_offset=3*u.hour)
TIMESTR_FORMAT = '%Y-%m-%d %H:%M:%S'
def str2date(timestr, tzone):
time_raw = datetime.strptime(timestr, TIMESTR_FORMAT)
time_zoned = time_raw.replace(tzinfo=tzone)
return time_zoned
def date2mission(dtime):
mjdref = Time(MJDREF, format='mjd')
dtime = Time(dtime , format='datetime')
return (dtime - mjdref).sec
def mission2date(timesec, tzone):
mjdref = Time(MJDREF, format='mjd')
delta = TimeDelta(timesec, format='sec')
dtime = mjdref + delta + 3*u.hour
return dtime.to_datetime()
def print_obsplan_dt_sec(dtstr):
dt = str2date(dtstr, tzone=TZ_MSK)
ts = date2mission(dt)
print(dt, '-->', ts)
def print_pz_dt_sec(dtstr):
dt = str2date(dtstr, tzone=TZ_UTC)
ts = date2mission(dt)
print(dt, '-->', ts)
def load_data(file):
print('Load data (dummy)')
csvfile=INPUT_DATA_DIR+'/'+file
df = pd.read_csv(csvfile,names=['name', 'path', 'filename', 'tstart','tstop'])
print(df)
for i in df.index:
dd = DataDump()
dd.start=mission2date(int(df['tstart'][i]), TZ_MSK)
dd.stop=mission2date(int(df['tstop'][i]), TZ_MSK)
dd.tstart=int(df['tstart'][i])
dd.tstop=int(df['tstop'][i])
dd.name=df['name'][i]
dd.filename=df['filename'][i]
dd.path=df['path'][i]
dd.save()
observations = Observation.objects.filter(Q(start__gte=dd.start) & Q(start__lte=dd.stop))
scans = Scan.objects.filter(Q(start__gte=dd.start) & Q(start__lte=dd.stop))
for observation in observations:
dd.observations.add(observation)
for scan in scans:
dd.scans.add(scan)
observations = Observation.objects.filter(Q(stop__gte=dd.start) & Q(stop__lte=dd.stop))
scans = Scan.objects.filter(Q(stop__gte=dd.start) & Q(stop__lte=dd.stop))
for observation in observations:
dd.observations.add(observation)
for scan in scans:
dd.scans.add(scan)
dd.save()
print(mission2date(int(df['tstart'][i]), TZ_MSK))
print(df['name'][i])
pass
def validate_flightplan():
list = FlightPlan.objects.all()
for pz in list:
if (pz.experiment == '00000000000' and pz.valid == True):
pz.valid = False
pz.save()
continue
first = FlightPlan.objects.filter(experiment__exact=pz.experiment).order_by("-load_stamp")[0]
first.valid = True
first.save()
pass
class Command(BaseCommand):
help = 'Initiates data base'
# def add_arguments(self, parser):
# parser.add_argument('poll_id', nargs='+', type=int)
def handle(self, *args, **options):
dds = DataDump.objects.all()
dds.delete()
load_data('read_seance.csv')
print_pz_dt_sec('2019-08-21 22:00:00')
print_pz_dt_sec('2019-08-21 23:00:00')
#validate_flightplan()

View File

@@ -0,0 +1,239 @@
from django.core.management.base import BaseCommand, CommandError
from datetime import date
from django.utils import dateparse
from logbook.models import LogBookPlan, LogBookDay
from plan.models import INPUT_DATA_DIR
from plan.models import LaunchDate
from monthplan.models import Head, Observation, Seance, Correction, Scan, Survey, FlightPlan, DataDump, SurveyPath
from monthplan.models import SurveyHealpixPlate, NSIDE_PLATES, ORDER
from astropy.io import fits
from datetime import datetime
from django.utils import timezone
from astropy.io import fits
import pandas as pd
from pandas import ExcelWriter
from pandas import ExcelFile
#import xlrd
from astropy.table import Table
import astropy.units as u
from astropy.time.formats import erfa
from astropy.time import Time, TimeDelta, TimezoneInfo, TimeFromEpoch
from django.db.models import Q
from math import pi, cos, sin
from Quaternion import Quat
from scipy.spatial.transform import Rotation, Slerp
import numpy as np
from srglib.utils import slerp, quat_to_pol_and_roll
import math
from Quaternion import Quat
from os import listdir
from astropy_healpix import HEALPix
from astropy import units as u
from astropy.coordinates import SkyCoord, RangeError
from astropy.coordinates import ICRS, Galactic, FK5
from astropy.coordinates import Angle
MJDREF = 51543.875
TZ_UTC = TimezoneInfo(utc_offset=0*u.hour)
TZ_MSK = TimezoneInfo(utc_offset=3*u.hour)
TIMESTR_FORMAT = '%Y.%m.%d %H:%M:%S'
def str2date(timestr, tzone):
time_raw = datetime.strptime(timestr, TIMESTR_FORMAT)
time_zoned = time_raw.replace(tzinfo=tzone)
return time_zoned
def date2mission(dtime):
mjdref = Time(MJDREF, format='mjd')
dtime = Time(dtime , format='datetime')
#print(dtime.mjd)
return (dtime - mjdref).sec
def mission2date(timesec, tzone):
mjdref = Time(MJDREF, format='mjd')
delta = TimeDelta(timesec, format='sec')
dtime = mjdref + delta + 3*u.hour
return dtime.to_datetime()
def print_obsplan_dt_sec(dtstr):
dt = str2date(dtstr, tzone=TZ_MSK)
ts = date2mission(dt)
print(dt, '-->', ts, ts/14400)
def print_pz_dt_sec(dtstr):
dt = str2date(dtstr, tzone=TZ_UTC)
ts = date2mission(dt)
print(dt, '-->', ts)
def quat_to_pol_and_roll(qfin):
"""
it is assumed that quaternion is acting on the sattelite coordinate system
in order to orient in in icrs coordinates
opaxis - define dirrection of the main axis (x axis [1, 0, 0] coinside with optical axis)
we assume that north is oriented along z coordinate, we also name this coordinate
north for detectors
"""
opaxis=[1, 0, 0]
north=[0, 0, 1]
opticaxis = qfin.apply(opaxis)
print(opticaxis)
dec = np.arctan(opticaxis[2]/np.sqrt(opticaxis[1]**2 + opticaxis[0]**2))
ra = np.arctan2(opticaxis[1], opticaxis[0])%(2.*pi)
print(ra/pi*180,dec/pi*180)
return
yzprojection = np.cross(opticaxis, north)
vort = np.cross(north, opaxis)
rollangle = np.arctan2(np.sum(yzprojection*qfin.apply(vort), axis=1),
np.sum(yzprojection*qfin.apply(north), axis=1))
print(ra, dec, rollangle)
return ra, dec, rollangle
def logic(index,nskip):
if index % nskip == 0:
return False
return True
"""
# Skip rows from based on condition like skip every 3rd line
usersDf = pd.read_csv('users.csv', skiprows= lambda x: logic(x) )
print('Contents of the Dataframe created by skipping every 3rd row from csv file ')
print(usersDf)
"""
def load_data(file,obsid,nskip):
print("Load data for %s" % file)
try:
survey=Survey.objects.get(experiment__exact=obsid)
except:
print("This survey is not found")
return
# remove all attached SurveyPath to this survey:
spath=survey.surveypath_set.all()
spath.delete()
csvfile=INPUT_DATA_DIR+'/'+file
df = pd.read_csv(csvfile,names=['date', 'time', 'q1', 'q2','q3','q4','dummy'], header=None, delim_whitespace=True, skipfooter=1, engine='python', skiprows = lambda x: logic(x, nskip))
tolerance = 10.0
hp = HEALPix(nside=NSIDE_PLATES, order=ORDER, frame=FK5())
for i in df.index:
dtstr="%s %s" % (df['date'][i], df['time'][i])
dt = str2date(dtstr, tzone=TZ_MSK)
ts = date2mission(dt)
eroday=ts/14400
dtime = Time(dt , format='datetime')
mjd=dtime.mjd
q1=df['q1'][i]
q2=df['q2'][i]
q3=df['q3'][i]
q4=df['q4'][i]
quat=Quat(attitude=[q2,q3,q4,q1])
sp=SurveyPath(survey=survey,dtime=dt,mjd=mjd,obt=ts,eroday=eroday,
q1=q1,q2=q2,q3=q3,q4=q4,ra=quat.ra,dec=quat.dec,roll=quat.roll)
sp.save()
print('Mark SurveyHealpixPlate')
surveypaths = survey.surveypath_set.all()
for i in range(len(surveypaths)-1):
delta=(surveypaths[i+1].dtime-surveypaths[i].dtime).total_seconds()
if(abs(int(delta)) > tolerance):
nstep = int(abs(delta) / tolerance)
delta_arr = np.linspace(0,1,nstep)
quat = slerp([surveypaths[i].q2, surveypaths[i].q3, surveypaths[i].q4, surveypaths[i].q1],
[surveypaths[i+1].q2, surveypaths[i+1].q3, surveypaths[i+1].q4, surveypaths[i+1].q1],
delta_arr)
for q in quat:
qfin=Quat(attitude=q)
crd = SkyCoord(qfin.ra, qfin.dec, frame="fk5", unit="deg")
heal = hp.skycoord_to_healpix(crd)
try:
plate = SurveyHealpixPlate.objects.get(healpix=heal)
except:
print('Error: SurveyHealpixPlate not found, run ./manage.py init_survey_healpix_plates first')
break
queryset = survey.surveyhealpixplate_set.all()
if not queryset.filter(pk=plate.pk).exists():
plate.survey.add(survey)
plate.save()
pass
class Command(BaseCommand):
help = 'Initiates data base'
# def add_arguments(self, parser):
# parser.add_argument('poll_id', nargs='+', type=int)
def handle(self, *args, **options):
"""
load_data('ARJ-SCAN/kvater22_23-09.rez','10000000100',100)
load_data('ARJ-SCAN/kvater23_24-09.rez','10000000200',100)
load_data('ARJ-SCAN/kvater14-11_13_35_00.rez','10000100100',100)
load_data('ARJ-SCAN/kvater15-11_14_35_00.rez','10000100200',100)
load_data('ARJ-SCAN/20191203_150000_10000200100.iki','10000200100',100)
load_data('ARJ-SCAN/20191208_170000_10000300100.iki','10000300100',100)
load_data('ARJ-SCAN/20191210_223000_10000400100.iki','10000400100',100)
load_data('ARJ-SCAN/20191212_003000_11000000100.iki','11000000100',100)
load_data('ARJ-SCAN/20191217_003000_11000000200.iki','11000000200',100)
load_data('ARJ-SCAN/20191222_003000_11000000300.iki','11000000300',100)
load_data('ARJ-SCAN/20191227_003000_11000000400.iki','11000000400',100)
load_data('ARJ-SCAN/20200101_003000_11000000500.iki','11000000500',100)
"""
""" Jan 2020 """
"""
load_data('ARJ-SCAN/20200102_163000_11000100100.iki','11000100100',1)
load_data('ARJ-SCAN/20200106_163000_11000100200.iki','11000100200',100)
load_data('ARJ-SCAN/20200110_163000_11000100300.iki','11000100300',100)
load_data('ARJ-SCAN/20200114_163000_11000100400.iki','11000100400',100)
load_data('ARJ-SCAN/20200118_163000_11000100500.iki','11000100500',100)
load_data('ARJ-SCAN/20200122_163000_11000100600.iki','11000100600',100)
load_data('ARJ-SCAN/20200126_163000_11000100700.iki','11000100700',100)
load_data('ARJ-SCAN/20200130_220000_11000200100.iki','11000200100',100)
"""
""" Feb 2020 """
#load_data('ARJ-SCAN/20200202_220000_11000300100.iki','11000300100',100)
#load_data('ARJ-SCAN/20200206_220000_11000300200.iki','11000300200',100)
#load_data('ARJ-SCAN/20200210_220000_11000300300.iki','11000300300',100)
#load_data('ARJ-SCAN/20200214_220000_11000400100.iki','11000400100',100)
load_data('ARJ-SCAN/20200218_220000_11000400200.iki','11000400200',100)
load_data('ARJ-SCAN/20200222_220000_11000400300.iki','11000400300',100)
load_data('ARJ-SCAN/20200226_220000_11000400400.iki','11000400400',100)
# invalid after eRosita reset
#load_data('ARJ-SCAN/20200214_220000_11000300400.iki','11000300400',100)
#load_data('ARJ-SCAN/20200218_220000_11000300500.iki','11000300500',100)
#load_data('ARJ-SCAN/20200222_220000_11000300600.iki','11000300600',100)
#load_data('ARJ-SCAN/20200226_220000_11000300700.iki','11000300700',100)

View File

@@ -0,0 +1,181 @@
from django.core.management.base import BaseCommand, CommandError
from datetime import date
from django.utils import dateparse
from logbook.models import LogBookPlan, LogBookDay
from plan.models import INPUT_DATA_DIR
from plan.models import LaunchDate
from monthplan.models import Head, Observation, Seance, Correction, Scan, Survey, FlightPlan, DataDump, SurveyPath
from astropy.io import fits
from datetime import datetime
from django.utils import timezone
from astropy.io import fits
import pandas as pd
from pandas import ExcelWriter
from pandas import ExcelFile
#import xlrd
from astropy.table import Table
import astropy.units as u
from astropy.time.formats import erfa
from astropy.time import Time, TimeDelta, TimezoneInfo, TimeFromEpoch
from django.db.models import Q
from math import pi, cos, sin
from Quaternion import Quat
from scipy.spatial.transform import Rotation, Slerp
import numpy as np
MJDREF = 51543.875
TZ_UTC = TimezoneInfo(utc_offset=0*u.hour)
TZ_MSK = TimezoneInfo(utc_offset=3*u.hour)
TIMESTR_FORMAT = '%Y.%m.%d %H:%M:%S'
def str2date(timestr, tzone):
time_raw = datetime.strptime(timestr, TIMESTR_FORMAT)
time_zoned = time_raw.replace(tzinfo=tzone)
return time_zoned
def date2mission(dtime):
mjdref = Time(MJDREF, format='mjd')
dtime = Time(dtime , format='datetime')
#print(dtime.mjd)
return (dtime - mjdref).sec
def mission2date(timesec, tzone):
mjdref = Time(MJDREF, format='mjd')
delta = TimeDelta(timesec, format='sec')
dtime = mjdref + delta + 3*u.hour
return dtime.to_datetime()
def print_obsplan_dt_sec(dtstr):
dt = str2date(dtstr, tzone=TZ_MSK)
ts = date2mission(dt)
print(dt, '-->', ts, ts/14400)
def print_pz_dt_sec(dtstr):
dt = str2date(dtstr, tzone=TZ_UTC)
ts = date2mission(dt)
print(dt, '-->', ts)
def quat_to_pol_and_roll(qfin):
"""
it is assumed that quaternion is acting on the sattelite coordinate system
in order to orient in in icrs coordinates
opaxis - define dirrection of the main axis (x axis [1, 0, 0] coinside with optical axis)
we assume that north is oriented along z coordinate, we also name this coordinate
north for detectors
"""
opaxis=[1, 0, 0]
north=[0, 0, 1]
opticaxis = qfin.apply(opaxis)
print(opticaxis)
dec = np.arctan(opticaxis[2]/np.sqrt(opticaxis[1]**2 + opticaxis[0]**2))
ra = np.arctan2(opticaxis[1], opticaxis[0])%(2.*pi)
print(ra/pi*180,dec/pi*180)
return
yzprojection = np.cross(opticaxis, north)
vort = np.cross(north, opaxis)
rollangle = np.arctan2(np.sum(yzprojection*qfin.apply(vort), axis=1),
np.sum(yzprojection*qfin.apply(north), axis=1))
print(ra, dec, rollangle)
return ra, dec, rollangle
def logic(index,nskip):
if index % nskip == 0:
return False
return True
def load_data(file,obsid,nskip):
print('Load data (dummy)')
try:
survey=Survey.objects.get(experiment__exact=obsid)
except:
print("This survey is not found")
return
# remove all attached SurveyPath to this survey:
spath=survey.surveypath_set.all()
spath.delete()
csvfile=INPUT_DATA_DIR+'/ARJ-SCAN/'+file
df = pd.read_csv(csvfile,names=['date', 'time', 'q1', 'q2','q3','q4','dummy'], header=None, delim_whitespace=True, skipfooter=1, skiprows = lambda x: logic(x, nskip))
print(df)
for i in df.index:
dtstr="%s %s" % (df['date'][i], df['time'][i])
dt = str2date(dtstr, tzone=TZ_MSK)
ts = date2mission(dt)
eroday=ts/14400
dtime = Time(dt , format='datetime')
mjd=dtime.mjd
q1=df['q1'][i]
q2=df['q2'][i]
q3=df['q3'][i]
q4=df['q4'][i]
quat=Quat(attitude=[q2,q3,q4,q1])
sp=SurveyPath(survey=survey,dtime=dt,mjd=mjd,obt=ts,eroday=eroday,q1=q1,q2=q2,q3=q3,q4=q4,ra=quat.ra,dec=quat.dec,roll=quat.roll)
sp.save()
pass
class Command(BaseCommand):
help = 'Initiates data base'
# def add_arguments(self, parser):
# parser.add_argument('poll_id', nargs='+', type=int)
def handle(self, *args, **options):
load_data('kvater22_23-09.rez','10000000100',50)
load_data('kvater23_24-09.rez','10000000200',50)
load_data('kvater14-11_13_35_00.rez','10000100100',50)
load_data('kvater15-11_14_35_00.rez','10000100200',50)
load_data('20191203_150000_10000200100.iki','10000200100',50)
load_data('20191208_170000_10000300100.iki','10000300100',50)
load_data('20191210_223000_10000400100.iki','10000400100',50)
load_data('20191212_003000_11000000100.iki','11000000100',50)
return
#
# Experiments:
#
# .407947163597554
# .826585167542578 ! 327.89199999
# -.077996859000543 ! -34.35000000
# -.379805953741339 ! .000
print('327.89199999 -34.35000000')
arr=[.826585167542578, -.077996859000543, -.379805953741339, .407947163597554]
#qfin = Rotation.from_quat(arr)
#qfin = Rotation.from_quat([0, 0, np.sin(np.pi/4), np.cos(np.pi/4)])
#print(qfin.as_euler('zyx', degrees=True))
#qadd=Rotation([0, 0, 0, 1])
#qfin=Rotation(arr)
#a = quat_to_pol_and_roll(qfin)
#print(a)
#print_obsplan_dt_sec('2019.10.16 10:42:04')
#print_obsplan_dt_sec('2019.10.17 00:47:42')
# # print_pz_dt_sec('2019.08.21 23:00:00')
print('***')
quat = Quat(attitude=arr)
print(quat.ra, quat.dec, quat.roll)
#validate_flightplan()

View File

@@ -0,0 +1,280 @@
from django.core.management.base import BaseCommand, CommandError
from datetime import date
from django.utils import dateparse
from logbook.models import LogBookPlan, LogBookDay
from plan.models import INPUT_DATA_DIR
from plan.models import LaunchDate
from monthplan.models import Head, Observation, Seance, Correction, Scan, Survey, FlightPlan, ScanPath
from astropy.io import fits
from datetime import datetime
from django.utils import timezone
from astropy.io import fits
import pandas as pd
from pandas import ExcelWriter
from pandas import ExcelFile
#import xlrd
from astropy.table import Table
import astropy.units as u
from astropy.time.formats import erfa
from astropy.time import Time, TimeDelta, TimezoneInfo, TimeFromEpoch
from django.db.models import Q
from math import pi, cos, sin
from Quaternion import Quat
from scipy.spatial.transform import Rotation, Slerp
import numpy as np
MJDREF = 51543.875
TZ_UTC = TimezoneInfo(utc_offset=0*u.hour)
TZ_MSK = TimezoneInfo(utc_offset=3*u.hour)
TIMESTR_FORMAT = '%Y.%m.%d %H:%M:%S'
def str2date(timestr, tzone):
#print(timestr)
if timestr.find('60') > 0:
timestr=timestr.replace('60', '00')
time_raw = datetime.strptime(timestr, TIMESTR_FORMAT)
time_zoned = time_raw.replace(tzinfo=tzone)
return time_zoned
def date2mission(dtime):
mjdref = Time(MJDREF, format='mjd')
dtime = Time(dtime , format='datetime')
#print(dtime.mjd)
return (dtime - mjdref).sec
def mission2date(timesec, tzone):
mjdref = Time(MJDREF, format='mjd')
delta = TimeDelta(timesec, format='sec')
dtime = mjdref + delta + 3*u.hour
return dtime.to_datetime()
def print_obsplan_dt_sec(dtstr):
dt = str2date(dtstr, tzone=TZ_MSK)
ts = date2mission(dt)
print(dt, '-->', ts, ts/14400)
def print_pz_dt_sec(dtstr):
dt = str2date(dtstr, tzone=TZ_UTC)
ts = date2mission(dt)
print(dt, '-->', ts)
def quat_to_pol_and_roll(qfin):
"""
it is assumed that quaternion is acting on the sattelite coordinate system
in order to orient in in icrs coordinates
opaxis - define dirrection of the main axis (x axis [1, 0, 0] coinside with optical axis)
we assume that north is oriented along z coordinate, we also name this coordinate
north for detectors
"""
opaxis=[1, 0, 0]
north=[0, 0, 1]
opticaxis = qfin.apply(opaxis)
print(opticaxis)
dec = np.arctan(opticaxis[2]/np.sqrt(opticaxis[1]**2 + opticaxis[0]**2))
ra = np.arctan2(opticaxis[1], opticaxis[0])%(2.*pi)
print(ra/pi*180,dec/pi*180)
return
yzprojection = np.cross(opticaxis, north)
vort = np.cross(north, opaxis)
rollangle = np.arctan2(np.sum(yzprojection*qfin.apply(vort), axis=1),
np.sum(yzprojection*qfin.apply(north), axis=1))
print(ra, dec, rollangle)
return ra, dec, rollangle
def logic(index,nskip):
if index % nskip == 0:
return False
return True
def load_data(file,obsid,nskip):
print('Load data for ',obsid)
try:
scan=Scan.objects.get(experiment__exact=obsid)
except:
print("This scan is not found ",obsid)
try:
scans=Scan.objects.filter(experiment__exact=obsid)
except:
print("Multiple scans were also not found ",obsid)
print('Remove some of the invalid scans below:')
for scan in scans:
print(scan.experiment,scan.start,scan.stop,scan.head)
return
# remove all attached ScanPath to this scan:
spath=scan.scanpath_set.all()
spath.delete()
csvfile=INPUT_DATA_DIR+'/ARJ-SCAN/'+file
df = pd.read_csv(csvfile,names=['date', 'time', 'q1', 'q2','q3','q4','dummy'], header=None, delim_whitespace=True, skipfooter=1, skiprows = lambda x: logic(x, nskip))
print(df)
for i in df.index:
dtstr="%s %s" % (df['date'][i], df['time'][i])
dt = str2date(dtstr, tzone=TZ_MSK)
ts = date2mission(dt)
eroday=ts/14400
dtime = Time(dt , format='datetime')
mjd=dtime.mjd
q1=df['q1'][i]
q2=df['q2'][i]
q3=df['q3'][i]
q4=df['q4'][i]
quat=Quat(attitude=[q2,q3,q4,q1])
sp=ScanPath(scan=scan,dtime=dt,mjd=mjd,obt=ts,eroday=eroday,q1=q1,q2=q2,q3=q3,q4=q4,ra=quat.ra,dec=quat.dec,roll=quat.roll)
sp.save()
pass
class Command(BaseCommand):
help = 'Initiates data base'
# def add_arguments(self, parser):
# parser.add_argument('poll_id', nargs='+', type=int)
def handle(self, *args, **options):
# note: delete 00003017001 scan from August plan
"""
load_data('kvater01-09_02_15_00.rez','00003017001')
load_data('kvater01-09_10_17_58.rez','00003017002')
load_data('kvater01-10_01_40_00.rez','00003044001')
load_data('kvater02-09_02_40_00.rez','00003031001')
load_data('kvater02-09_10_42_58.rez','00003031002')
load_data('kvater02-10_01_10-00.rez','00003045001')
load_data('kvater03-09_04_06_00.rez','00003018001')
load_data('kvater03-09_11_22_58.rez','00003018002')
load_data('kvater03-11_05_25_50.rez','30000700100')
load_data('kvater04-09_04_06_00.rez','00003019001')
load_data('kvater04-09_11_22_58.rez','00003019002')
load_data('kvater04-11_07_05_52.rez','30000800100')
load_data('kvater05-09_04_06_00.rez','00003020001')
load_data('kvater05-09_11_22_58.rez','00003020002')
load_data('kvater05-11_08_45_54.rez','30000900100')
load_data('kvater06-09_04_06_00.rez','00003021001')
load_data('kvater06-09_11_22_58.rez','00003021002')
load_data('kvater06-11_10_25_56.rez','30001000100')
load_data('kvater07-09_04_06_00.rez','00003022001')
load_data('kvater07-09_11_22_58.rez','00003022002')
load_data('kvater08-09_01_40_00.rez','00003023001')
load_data('kvater08-10_19_11_10.rez','30000500100')
load_data('kvater09-09_01_40_00.rez','00003024001')
load_data('kvater09-10_12_20_02.rez','30000600100')
load_data('kvater10-09_01_30_00.rez','00003025001')
load_data('kvater11-09_01_40_00.rez','00003026001')
load_data('kvater12-09_04_06_00.rez','00003027001')
load_data('kvater12-09_11_22_58.rez','00003027002')
load_data('kvater13-09_04_06_00.rez','00003028001')
load_data('kvater13-09_11_22_58.rez','00003028002')
load_data('kvater13-10_08_59_10.rez','50000600100')
load_data('kvater13-10_23_48_18.rez','50000700100')
load_data('kvater14-08_12_50_00.rez','00003021001')
load_data('kvater14-09_04_06_00.rez','00003029001')
load_data('kvater14-09_11_22_58.rez','00003029002')
load_data('kvater15-09_03_03_20.rez','70004000100')
load_data('kvater15-10_19_52_56.rez','50000800100')
load_data('kvater16-10_10_42_04.rez','50000900100')
load_data('kvater17-08_02_00_00.rez','00003001001')
load_data('kvater17-08_11_01_00.rez','00003002001')
load_data('kvater17-08_22_10_00.rez','00003003001')
load_data('kvater17-09_04_06_00.rez','00003032001')
load_data('kvater17-09_11-22_58.rez','00003032002')
load_data('kvater18-08_03_58_19.rez','00003003002')
load_data('kvater18-08_09_46_38.rez','00003003003')
load_data('kvater18-08_22_10_00.rez','00003004001')
load_data('kvater18-09_04_06_00.rez','00003033001')
load_data('kvater18-09_11_22_58.rez','00003033002')
load_data('kvater18-10_03_16_32.rez','30001600100')
load_data('kvater19-08_01_38_28.rez','00003004002')
load_data('kvater19-08_05_06_56.rez','00003004003')
load_data('kvater19-08_08_35_24.rez','00003004004')
load_data('kvater19-08_12_03_52.rez','00003004005')
load_data('kvater19-08_22_10_00.rez','00003005001')
load_data('kvater19-09_01_40_00.rez','00003034001')
load_data('kvater20-08_01_29_18.rez','00003005002')
load_data('kvater20-08_06_48_36.rez','00003005003')
load_data('kvater20-08_11_07_54.rez','00003005004')
load_data('kvater20-08_22_10_00.rez','00003006001')
load_data('kvater20-09_01_40_00.rez','00003035001')
load_data('kvater20-09_06_18_00.rez','00003036001')
load_data('kvater20-09_10_56_00.rez','00003037001')
load_data('kvater21-08_02_29_18.rez','00003006002')
load_data('kvater21-08_06_48_36.rez','00003006003')
load_data('kvater21-08_11_07_54.rez','00003006004')
load_data('kvater21-09_01_27_00.rez','00003030001')
load_data('kvater21-09_08_43_58.rez','00003030002')
load_data('kvater22-08_22_10_00.rez','00003007001')
load_data('kvater23-08_01_38_28.rez','00003007002')
load_data('kvater23-08_05_06_56.rez','00003007003')
load_data('kvater23-08_08_35_24.rez','00003007004')
load_data('kvater23-08_12_03_52.rez','00003007005')
load_data('kvater23-08_22_10_00.rez','00003008001')
load_data('kvater24-08_02_47_38.rez','00003008002')
load_data('kvater24-08_07_25_16.rez','00003008003')
load_data('kvater24-08_12_02_54.rez','00003008004')
load_data('kvater24-08_22_10_00.rez','00003009001')
load_data('kvater24-09_03_30_00.rez','00003041001')
load_data('kvater24-09_11_07_09.rez','00003041001')
load_data('kvater24-09_13_05_00.rez','00003042001')
load_data('kvater24-09_15_02_09.rez','00003042002')
load_data('kvater25-08_02_47_38.rez','00003009002')
load_data('kvater25-08_07_25_16.rez','00003009003')
load_data('kvater25-08_12_02_54.rez','00003009004')
load_data('kvater25-08_22_10_00.rez','00003010001')
load_data('kvater25-09_01_40_00.rez','00003038001')
load_data('kvater26-08_02_47_38.rez','00003010002')
load_data('kvater26-08_12_02_54.rez','00003010004')
load_data('kvater26-08_23_40_00.rez','00003011001')
load_data('kvater26-09_01_40_00.rez','00003039001')
load_data('kvater26_08_07_25_16.rez','00003010003')
load_data('kvater27-08_04_17_38.rez','00003011002')
load_data('kvater27-08_08_55_16.rez','00003011003')
load_data('kvater27-08_13_32_54.rez','00003011004')
load_data('kvater27-08_23_40_00.rez','00003012001')
load_data('kvater27-09_01_40_00.rez','00003040001')
load_data('kvater28-08_04_17_38.rez','00003012002')
load_data('kvater28-08_08_55_16.rez','00003012003')
load_data('kvater28-08_13_32_54.rez','00003012004')
load_data('kvater28-08_23_40_00.rez','00003013001')
load_data('kvater28-09_01_40_00.rez','00003043001')
load_data('kvater29-08_04_17_38.rez','00003013002')
load_data('kvater29-08_08_55_16.rez','00003013003')
load_data('kvater30-08_02_40_00.rez','00003015001')
load_data('kvater30-08_10_42_58.rez','00003015002')
load_data('kvater31-08_02_40_00.rez','00003016001')
load_data('kvater31-08_10_42_58.rez','00003016002')
load_data('kvater12-11_03_04_38.rez','50001500100')
load_data('kvater12-11_21_50_31.rez','50001600100')
load_data('kvater13-11_11_06_34.rez','50001700100')
load_data('kvater14-11_00_22_37.rez','50001800100')
load_data('kvater16-11_07_42_50.rez','50001900100')
load_data('kvater16-11_16_47_48.rez','50002000100')
"""
"""
load_data('70019900100.iki','70019900100')
load_data('70020000100.iki','70020000100')
"""
load_data('70020100100.iki','70020100100',10)
load_data('20191204_041000_70020200100.iki','70020200100',10)
load_data('20191204_134001_50002600100.iki','50002600100',10)
load_data('20191205_005349_50002700100.iki','50002700100',10)
load_data('20191205_120737_50002800100.iki','50002800100',10)
load_data('20191205_232125_50002900100.iki','50002900100',10)
load_data('20191206_103513_50003000100.iki','50003000100',10)
load_data('20191207_071532_70020400100.iki','70020400100',10)
load_data('20191206_222021_70020300100.iki','70020300100',10)

View File

@@ -0,0 +1,36 @@
from django.core.management.base import BaseCommand, CommandError
from monthplan.models import SurveyHealpixPlate, NSIDE_PLATES, ORDER
from os import listdir
from astropy_healpix import HEALPix
from astropy import units as u
from astropy.coordinates import SkyCoord, RangeError
from astropy.coordinates import ICRS, Galactic, FK5
from astropy.coordinates import Angle
def init_healpix_plates(nside, order):
hp = HEALPix(nside=nside, order=order, frame=FK5())
print("Make Healpix Plates",hp.npix,hp.pixel_area.value,hp.pixel_resolution.value)
try:
print('Delete existing Healpix Plates')
plates = SurveyHealpixPlate.objects.all()
plates.delete()
except:
print('Abort')
exit()
for heal in range(hp.npix):
sc = hp.healpix_to_skycoord(heal)
plate = SurveyHealpixPlate(healpix=heal, ra=float(sc.ra.degree), dec=float(sc.dec.degree))
plate.save()
pass
class Command(BaseCommand):
def handle(self, *args, **options):
init_healpix_plates(NSIDE_PLATES, ORDER)

View File

@@ -0,0 +1,46 @@
from django.core.management.base import BaseCommand, CommandError
from monthplan.models import SurveyHealpixPlate, SurveyHealpixSubPlate, NSIDE_PLATES, NSIDE_SUBPLATES, ORDER
from os import listdir
from astropy_healpix import HEALPix
from astropy import units as u
from astropy.coordinates import SkyCoord, RangeError
from astropy.coordinates import ICRS, Galactic, FK5
from astropy.coordinates import Angle
def init_healpix_sub_plates(nside_plates, nside_subplates, order):
hp_plates = HEALPix(nside=nside_plates, order=order, frame=FK5())
hp_subplates = HEALPix(nside=nside_subplates, order=order, frame=FK5())
print("Make Healpix Plates",hp_plates.npix,hp_plates.pixel_area.value,hp_plates.pixel_resolution.value)
print("Make Healpix SubPlates",hp_subplates.npix,hp_subplates.pixel_area.value,hp_subplates.pixel_resolution.value)
try:
print('Delete existing Healpix Plates')
subplates = SurveyHealpixSubPlate.objects.all()
subplates.delete()
except:
print('Abort')
exit()
for heal in range(hp_subplates.npix):
sc = hp_subplates.healpix_to_skycoord(heal)
crd = SkyCoord(float(sc.ra.degree), float(sc.dec.degree), frame="fk5", unit="deg")
heal = hp_plates.skycoord_to_healpix(crd)
try:
plate = SurveyHealpixPlate.objects.get(healpix=heal)
except:
print('Error: SurveyHealpixPlate not found, run ./manage.py init_survey_healpix_plates first')
return
subplate = SurveyHealpixSubPlate(healpix=heal, ra=float(sc.ra.degree), dec=float(sc.dec.degree), plate=plate)
subplate.save()
pass
class Command(BaseCommand):
def handle(self, *args, **options):
init_healpix_sub_plates(NSIDE_PLATES, NSIDE_SUBPLATES, ORDER)

View File

@@ -0,0 +1,54 @@
from django.core.management.base import BaseCommand, CommandError
from monthplan.models import SurveyHealpixPlate, NSIDE_PLATES, ORDER, MAPS_DIR, Survey, SurveyPath
from os import listdir
from astropy_healpix import HEALPix
from astropy import units as u
from astropy.coordinates import SkyCoord, RangeError
from astropy.coordinates import ICRS, Galactic, FK5
from astropy.coordinates import Angle
import numpy as np
from srglib.utils import slerp, quat_to_pol_and_roll
import math
from Quaternion import Quat
class Command(BaseCommand):
def handle(self, *args, **options):
tolerance = 10.0
hp = HEALPix(nside=NSIDE_PLATES, order=ORDER, frame=FK5())
surveys=Survey.objects.all()
for survey in surveys:
print(survey.experiment)
surveypaths = survey.surveypath_set.all()
for i in range(len(surveypaths)-1):
delta=(surveypaths[i+1].dtime-surveypaths[i].dtime).total_seconds()
if(abs(int(delta)) > tolerance):
nstep = int(abs(delta) / tolerance)
delta_arr = np.linspace(0,1,nstep)
quat = slerp([surveypaths[i].q2, surveypaths[i].q3, surveypaths[i].q4, surveypaths[i].q1],
[surveypaths[i+1].q2, surveypaths[i+1].q3, surveypaths[i+1].q4, surveypaths[i+1].q1],
delta_arr)
for q in quat:
qfin=Quat(attitude=q)
crd = SkyCoord(qfin.ra, qfin.dec, frame="fk5", unit="deg")
heal = hp.skycoord_to_healpix(crd)
try:
plate = SurveyHealpixPlate.objects.get(healpix=heal)
except:
print('Error: SurveyHealpixPlate not found, run ./manage.py init_survey_healpix_plates first')
break
queryset = survey.surveyhealpixplate_set.all()
if not queryset.filter(pk=plate.pk).exists():
plate.survey.add(survey)
plate.save()

View File

@@ -0,0 +1,91 @@
from django.core.management.base import BaseCommand, CommandError
from datetime import datetime as dt
from datetime import date
from django.utils import dateparse
from logbook.models import LogBookPlan, LogBookDay
from plan.models import INPUT_DATA_DIR
from plan.models import LaunchDate
from srglib.utils import make_source_name
from monthplan.models import Head, Observation, Seance, Correction, Scan, Survey, FlightPlan
from astropy.io import fits
import datetime
from django.utils import timezone
from astropy.io import fits
import pandas as pd
from pandas import ExcelWriter
from pandas import ExcelFile
#import xlrd
from astropy.table import Table
import math
from django.db.models import Q
def find_closest(now, closest_greater_qs, closest_less_qs):
try:
try:
closest_greater = closest_greater_qs[0]
except IndexError:
closest = closest_less_qs[0]
try:
closest_less = closest_less_qs[0]
except IndexError:
closest = closest_greater_qs[0]
except IndexError:
raise self.model.DoesNotExist("There is no closest object"
" because there are no objects.")
if closest_greater.dtime - now > now - closest_less.dtime:
closest = closest_less
else:
closest = closest_greater
return closest.ra, closest.dec
class Command(BaseCommand):
help = 'Initiates data base'
# def add_arguments(self, parser):
# parser.add_argument('poll_id', nargs='+', type=int)
def handle(self, *args, **options):
name = make_source_name('SRG A',0.87,45.0)
print(name)
return
now = timezone.localtime(timezone.now())
print(now)
ra='n/a'
dec='n/a'
request_path='load'
try:
surveys = Survey.objects.filter(Q(start__lte=now) & Q(stop__gte=now))
# take first element only:
for survey in surveys:
print(survey.ra_p)
target = survey.target
obsid = survey.experiment
url = survey.get_absolute_url()
ra="%.4f" % survey.ra_p
dec="%.4f" % survey.dec_p
mode='Survey'
if request_path == "load":
path=list(survey.surveypath_set.all().values('ra', 'dec'))[::500]
closest_greater_qs = survey.surveypath_set.filter(dtime__gt=now).order_by('dtime')
closest_less_qs = survey.surveypath_set.filter(dtime__lt=now).order_by('-dtime')
closest_ra, closest_dec = find_closest(now, closest_greater_qs, closest_less_qs)
ra="%.4f" % closest_ra
dec="%.4f" % closest_dec
print("*** closest found ***")
break
except NameError as error:
print('pass',error)
pass
print(ra, dec)

View File

@@ -0,0 +1,34 @@
from django.core.management.base import BaseCommand, CommandError
from datetime import date
from django.utils import dateparse
from logbook.models import LogBookPlan, LogBookDay
from plan.models import INPUT_DATA_DIR
from plan.models import LaunchDate
from django.contrib.auth.models import User
from monthplan.models import Head, Observation, Seance, Correction, Scan, Survey, FlightPlan
from astropy.io import fits
import datetime
from django.utils import timezone
class Command(BaseCommand):
help = 'Initiates data base'
# def add_arguments(self, parser):
# parser.add_argument('poll_id', nargs='+', type=int)
def handle(self, *args, **options):
user = User.objects.get(id=2)
user_email = user.email
print(user_email)
emails = []
users = User.objects.all()
for user in users:
emails.append(user.email)
print(emails)

View File

@@ -0,0 +1,206 @@
# Generated by Django 2.2.6 on 2019-12-09 18:37
import django.core.files.storage
from django.db import migrations, models
import django.db.models.deletion
import monthplan.models
class Migration(migrations.Migration):
initial = True
dependencies = [
('plan', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='FlightPlan',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('experiment', models.CharField(max_length=11)),
('ra', models.FloatField(default=0.0)),
('dec', models.FloatField(default=0.0)),
('start', models.DateTimeField(blank=True)),
('stop', models.DateTimeField(blank=True)),
('q1', models.FloatField(default=0.0)),
('q2', models.FloatField(default=0.0)),
('q3', models.FloatField(default=0.0)),
('q4', models.FloatField(default=0.0)),
('start_npol', models.CharField(max_length=25)),
('stop_npol', models.CharField(max_length=25)),
('load_stamp', models.DateTimeField(blank=True)),
('mjd_start', models.FloatField(default=0.0)),
('mjd_stop', models.FloatField(default=0.0)),
('obt_start', models.FloatField(default=0.0)),
('obt_stop', models.FloatField(default=0.0)),
('valid', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name='Head',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('guid', models.CharField(blank=True, default='', max_length=36)),
('start', models.DateTimeField(blank=True)),
('stop', models.DateTimeField(blank=True)),
('title', models.CharField(blank=True, default='', max_length=128)),
('version', models.IntegerField(default=0)),
('gentime', models.DateTimeField(blank=True)),
('author', models.CharField(max_length=80)),
('nrows', models.IntegerField(default=0)),
('archived', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name='Scan',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('guid', models.CharField(max_length=36)),
('experiment', models.CharField(max_length=11)),
('target', models.CharField(default='', max_length=50)),
('ra', models.FloatField(default=0.0)),
('dec', models.FloatField(default=0.0)),
('start', models.DateTimeField(blank=True)),
('stop', models.DateTimeField(blank=True)),
('roll_angle', models.FloatField(default=0.0)),
('sun_xoz_angle', models.FloatField(default=0.0)),
('template', models.IntegerField(default=0)),
('row', models.IntegerField(default=0)),
('ra_obj', models.FloatField(default=0.0)),
('dec_obj', models.FloatField(default=0.0)),
('name_obj', models.CharField(default='', max_length=30)),
('head', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='monthplan.Head')),
],
),
migrations.CreateModel(
name='Survey',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('guid', models.CharField(max_length=36)),
('experiment', models.CharField(max_length=11)),
('target', models.CharField(default='', max_length=50)),
('start', models.DateTimeField(blank=True)),
('stop', models.DateTimeField(blank=True)),
('ra_p', models.FloatField(default=0.0)),
('dec_p', models.FloatField(default=0.0)),
('ra_z0', models.FloatField(default=0.0)),
('dec_z0', models.FloatField(default=0.0)),
('ra_zk', models.FloatField(default=0.0)),
('dec_zk', models.FloatField(default=0.0)),
('z_speed', models.FloatField(default=0.0, help_text='deg/day')),
('row', models.IntegerField(default=0)),
('head', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='monthplan.Head')),
],
),
migrations.CreateModel(
name='SurveyPath',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dtime', models.DateTimeField(blank=True)),
('obt', models.FloatField(default=0.0)),
('eroday', models.FloatField(default=0.0)),
('mjd', models.FloatField(default=0.0)),
('ra', models.FloatField(default=0.0)),
('dec', models.FloatField(default=0.0)),
('roll', models.FloatField(default=0.0)),
('q1', models.FloatField(default=0.0)),
('q2', models.FloatField(default=0.0)),
('q3', models.FloatField(default=0.0)),
('q4', models.FloatField(default=0.0)),
('survey', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='monthplan.Survey')),
],
),
migrations.CreateModel(
name='Seance',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('guid', models.CharField(max_length=36)),
('start', models.DateTimeField(blank=True)),
('stop', models.DateTimeField(blank=True)),
('stations', models.CharField(max_length=36)),
('row', models.IntegerField(default=0)),
('head', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='monthplan.Head')),
],
),
migrations.CreateModel(
name='ScanPath',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dtime', models.DateTimeField(blank=True)),
('obt', models.FloatField(default=0.0)),
('eroday', models.FloatField(default=0.0)),
('mjd', models.FloatField(default=0.0)),
('ra', models.FloatField(default=0.0)),
('dec', models.FloatField(default=0.0)),
('roll', models.FloatField(default=0.0)),
('q1', models.FloatField(default=0.0)),
('q2', models.FloatField(default=0.0)),
('q3', models.FloatField(default=0.0)),
('q4', models.FloatField(default=0.0)),
('scan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='monthplan.Scan')),
],
),
migrations.CreateModel(
name='Observation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('guid', models.CharField(max_length=36)),
('experiment', models.CharField(max_length=11)),
('target', models.CharField(default='', max_length=50)),
('ra', models.FloatField(default=0.0)),
('dec', models.FloatField(default=0.0)),
('start', models.DateTimeField(blank=True)),
('stop', models.DateTimeField(blank=True)),
('roll_angle', models.FloatField(default=0.0)),
('sun_xoz_angle', models.FloatField(default=0.0)),
('row', models.IntegerField(default=0)),
('ra_obj', models.FloatField(default=0.0)),
('dec_obj', models.FloatField(default=0.0)),
('name_obj', models.CharField(default='', max_length=30)),
('head', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='monthplan.Head')),
],
),
migrations.CreateModel(
name='MonthPlanUpload',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(blank=True, max_length=128)),
('filename', models.CharField(max_length=256)),
('filefield', models.FileField(storage=django.core.files.storage.FileSystemStorage(location='/srv/srg-plan/srg/Uploads/monthplan'), upload_to=monthplan.models.upload_filename, validators=[monthplan.models.validate_upload_file])),
('uploaded', models.DateTimeField(auto_now_add=True)),
('head', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='upload', to='monthplan.Head', verbose_name='month plan')),
('owner', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='MonthPlanOwner', to='plan.UserProfile', verbose_name='Author')),
],
),
migrations.CreateModel(
name='DataDump',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=36)),
('start', models.DateTimeField(blank=True, null=True)),
('stop', models.DateTimeField(blank=True, null=True)),
('tstart', models.BigIntegerField(default=0)),
('tstop', models.BigIntegerField(default=0)),
('path', models.CharField(max_length=120)),
('filename', models.CharField(max_length=50)),
('mjd_start', models.FloatField(default=0.0)),
('mjd_stop', models.FloatField(default=0.0)),
('observations', models.ManyToManyField(to='monthplan.Observation')),
('scans', models.ManyToManyField(to='monthplan.Scan')),
],
),
migrations.CreateModel(
name='Correction',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('guid', models.CharField(max_length=36)),
('start', models.DateTimeField(blank=True)),
('stop', models.DateTimeField(blank=True)),
('impstart', models.DateTimeField(blank=True)),
('row', models.IntegerField(default=0)),
('head', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='monthplan.Head')),
],
),
]

View File

@@ -0,0 +1,30 @@
# Generated by Django 2.2.6 on 2019-12-09 22:33
import django.core.files.storage
from django.db import migrations, models
import monthplan.models
class Migration(migrations.Migration):
dependencies = [
('monthplan', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='monthplanupload',
name='filefield',
field=models.FileField(storage=django.core.files.storage.FileSystemStorage(location='/export/django/srg/Uploads/monthplan'), upload_to=monthplan.models.upload_filename, validators=[monthplan.models.validate_upload_file]),
),
migrations.CreateModel(
name='SurveyHealpixPlate',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('healpix', models.BigIntegerField(db_index=True, default=0)),
('ra', models.FloatField(default=0.0)),
('dec', models.FloatField(default=0.0)),
('survey', models.ManyToManyField(to='monthplan.Survey')),
],
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 2.2.6 on 2020-02-10 12:03
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('monthplan', '0002_auto_20191209_2233'),
]
operations = [
migrations.AlterModelOptions(
name='surveypath',
options={'ordering': ['obt']},
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 2.2.6 on 2020-03-06 07:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('monthplan', '0003_auto_20200210_1503'),
]
operations = [
migrations.AddField(
model_name='survey',
name='loaded',
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,33 @@
# Generated by Django 2.2.6 on 2020-03-06 07:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('monthplan', '0004_survey_loaded'),
]
operations = [
migrations.AddField(
model_name='survey',
name='eroday_start',
field=models.FloatField(default=0.0),
),
migrations.AddField(
model_name='survey',
name='eroday_stop',
field=models.FloatField(default=0.0),
),
migrations.AddField(
model_name='survey',
name='mjd_start',
field=models.FloatField(default=0.0),
),
migrations.AddField(
model_name='survey',
name='mjd_stop',
field=models.FloatField(default=0.0),
),
]

View File

@@ -0,0 +1,24 @@
# Generated by Django 2.2.6 on 2020-03-21 17:57
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('monthplan', '0005_auto_20200306_1022'),
]
operations = [
migrations.CreateModel(
name='SurveyHealpixSubPlate',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('healpix', models.BigIntegerField(db_index=True, default=0)),
('ra', models.FloatField(default=0.0)),
('dec', models.FloatField(default=0.0)),
('plate', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='monthplan.SurveyHealpixPlate')),
],
),
]

View File

@@ -0,0 +1,78 @@
# Generated by Django 3.2.10 on 2021-12-29 09:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('monthplan', '0006_surveyhealpixsubplate'),
]
operations = [
migrations.AlterField(
model_name='correction',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='datadump',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='flightplan',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='head',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='monthplanupload',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='observation',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='scan',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='scanpath',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='seance',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='survey',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='surveyhealpixplate',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='surveyhealpixsubplate',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='surveypath',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
]

View File

524
monthplan/models.py Normal file
View File

@@ -0,0 +1,524 @@
from django.db import models
from django.core.files.storage import FileSystemStorage
from datetime import date, datetime
from datetime import timedelta
from django.utils.timezone import localdate, localtime
from logbook.models import INPUT_DATA_DIR
from plan.models import UserProfile
from django import forms
import hashlib
import os, os.path as osp
from django.utils.translation import gettext_lazy
import time
# Create your models here.
# [head]
# // SRG Month plan for Month Year
# // All times are given in UTC+3
# GUID = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# PROJECT = RG
# PLANNING_TERM = month
# START = dd.mm.yyyy
# STOP = dd.mm.yyyy
# VERSION = vv
# GENTIME = dd.mm.yyyy hh:mm:ss
# AUTHOR = Name, E-mail
MONTH_PLAN_UPLOAD_DIR = '/export/django/srg/Uploads/monthplan'
FS = FileSystemStorage(location=MONTH_PLAN_UPLOAD_DIR)
def upload_filename(instance, filename):
_, ext = osp.splitext(filename)
tohash = filename + str(time.clock())
new_fname = hashlib.md5(tohash.encode('utf-8')).hexdigest()
return new_fname + ext
class Head(models.Model):
""" Main class for month plan """
guid = models.CharField(max_length=36,blank=True, default='')
""" GUID (mostly not used) """
start = models.DateTimeField(blank=True)
""" Start DateTime Field """
stop = models.DateTimeField(blank=True)
""" Stop DateTime Field """
title = models.CharField(max_length=128,default='', blank=True)
""" Title """
version = models.IntegerField(default=0)
""" Version """
gentime = models.DateTimeField(blank=True)
""" Generation time """
author = models.CharField(max_length=80)
""" Author """
#file = models.FileField(storage=FS, blank=True, max_length=100)
nrows = models.IntegerField(default=0)
archived = models.BooleanField(default=False)
""" Archived or not """
def __str__(self):
dt = self.get_datetime()
return 'MonthPlan: ' + "%d-%02d" % (dt.year, dt.month)
def get_absolute_url(self):
return "/monthplan/%i/table" % (self.pk)
def get_absolute_url_seance(self):
return "/monthplan/%i/seance" % (self.pk)
def get_absolute_url_share(self):
return "/monthplan/%i/share" % (self.pk)
def get_absolute_url_observation(self):
return "/monthplan/%i/observation" % (self.pk)
def get_absolute_url_aladin(self):
return "/monthplan/%i/aladin" % (self.pk)
def get_absolute_url_scan(self):
return "/monthplan/%i/scan" % (self.pk)
def get_absolute_url_survey(self):
return "/monthplan/%i/survey" % (self.pk)
def get_absolute_url_correction(self):
return "/monthplan/%i/correction" % (self.pk)
def get_absolute_url_delete(self):
return "/monthplan/%i/delete" % (self.pk)
@property
def get_datetime_middle(self):
return self.start+timedelta(days=10)
def get_datetime(self):
return self.start+timedelta(days=10)
class FlightPlan(models.Model):
""" Fligh plan or Peletnoe Zadanie """
experiment = models.CharField(max_length=11)
""" ObsID """
ra = models.FloatField(default=0.0)
""" RA """
dec = models.FloatField(default=0.0)
""" Dec """
start = models.DateTimeField(blank=True)
""" Start """
stop = models.DateTimeField(blank=True)
""" Stop """
q1 = models.FloatField(default=0.0)
""" Quat 1 """
q2 = models.FloatField(default=0.0)
""" Quat 2 """
q3 = models.FloatField(default=0.0)
""" Quat 3 """
q4 = models.FloatField(default=0.0)
""" Quat 4 """
start_npol = models.CharField(max_length=25)
""" Original start time from NPOL """
stop_npol = models.CharField(max_length=25)
""" Original stop time from NPOL """
load_stamp = models.DateTimeField(blank=True)
""" When uploaded to SRG """
mjd_start = models.FloatField(default=0.0)
""" MJD start """
mjd_stop = models.FloatField(default=0.0)
""" MJD stop """
obt_start = models.FloatField(default=0.0)
""" On-board time start """
obt_stop = models.FloatField(default=0.0)
""" On-board time start """
valid = models.BooleanField(default=False)
""" Valid or not """
def __str__(self):
return "%s, %s (UTC), %s" % (self.experiment, self.load_stamp, self.valid)
@property
def is_past_due(self):
return localtime() > self.stop
@property
def is_future(self):
return localtime() < self.start
@property
def is_current(self):
return (localtime() > self.start and localtime() < self.stop)
def get_absolute_url(self):
return "/monthplan/%i/getpz" % (self.pk)
VALID_EXTENSIONS = ['.pdf', '.ppt', '.pptx', '.png', '.txt', '.dat', '.xlsx','.docx','.fits','.gz','.jpg','.jpeg',]
def validate_upload_file(value):
""" Validate uploaded file for extention """
file = value.file
_, ext = osp.splitext(file.name)
if ext not in VALID_EXTENSIONS:
raise forms.ValidationError(
'Extension %s not supported.' % ext
)
class MonthPlanUpload(models.Model):
""" Class for uploaded month-plan file """
owner = models.ForeignKey(UserProfile,
on_delete=models.CASCADE,
default=None,
unique=False,
verbose_name="Author",
related_name="MonthPlanOwner")
#head = models.ForeignKey(Head, unique=True, verbose_name="month plan", on_delete=models.CASCADE)
head = models.OneToOneField(Head,
verbose_name="month plan",
on_delete=models.CASCADE,
null=True, blank=True,
related_name='upload')
""" Related month plan :class:`Head` class """
title = models.CharField(max_length=128,blank=True)
""" Title of the file (not actually used) """
filename = models.CharField(max_length=256)
""" Filename """
filefield = models.FileField(upload_to=upload_filename, storage=FS, validators=[validate_upload_file])
""" Django FileField class """
uploaded = models.DateTimeField(auto_now_add=True)
""" When uploaded """
def get_filename(self):
return self.filename
def get_absolute_url(self):
return "/uploads/monthplan/%s" % (self.filefield)
def get_delete_url(self):
return self.head.get_absolute_url() + "/upload/%d/delete" % (self.id)
def delete(self, remove_file=True):
if remove_file:
FS.delete(str(self.filefield))
return models.Model.delete(self)
def __str__(self):
return 'MonthPlan '+self.title
class MonthPlanUploadForm(forms.ModelForm):
""" Form for file upload """
class Meta:
model = MonthPlanUpload
fields = ('filefield',)
# widgets = {
# 'title': forms.TextInput(attrs={'style': 'width: 620px;', 'class': 'title'}),
# }
# [observation]
# GUID = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# EXPERIMENT = AAAAAAAAA
# RA = XXX.XXXXXXXX // J2000
# DEC = zYY.YYYYYYYY // J2000
# START = dd.mm.yyyy hh:mm:ss
# STOP = dd.mm.yyyy hh:mm:ss
# ROLL_ANGLE = zXXX.X // Reference value
# SUN_XOZ_ANGLE = zXX.X
class Observation(models.Model):
"""Observation class
[observation]
GUID = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
EXPERIMENT = AAAAAAAAA
RA = XXX.XXXXXXXX // J2000
DEC = zYY.YYYYYYYY // J2000
START = dd.mm.yyyy hh:mm:ss
STOP = dd.mm.yyyy hh:mm:ss
ROLL_ANGLE = zXXX.X // Reference value
SUN_XOZ_ANGLE = zXX.X
"""
head = models.ForeignKey(Head, on_delete=models.CASCADE)
""" Related month plan :class:`Head` class """
guid = models.CharField(max_length=36)
""" GUID (not actually used) """
experiment = models.CharField(max_length=11)
""" ObsID """
target = models.CharField(max_length=50, default='')
""" Target """
ra = models.FloatField(default=0.0)
""" RA """
dec = models.FloatField(default=0.0)
""" Dec """
start = models.DateTimeField(blank=True)
""" Start """
stop = models.DateTimeField(blank=True)
""" Stop """
roll_angle = models.FloatField(default=0.0)
""" Roll angle """
sun_xoz_angle = models.FloatField(default=0.0)
""" SUN XOZ ANGLE """
row = models.IntegerField(default=0)
""" Row """
ra_obj = models.FloatField(default=0.0)
""" RA of the Object """
dec_obj = models.FloatField(default=0.0)
""" Dec of the Object """
name_obj = models.CharField(max_length=30, default='')
""" Name of the Object """
def get_absolute_url(self):
return "/monthplan/%i/getobs" % (self.pk)
def get_absolute_url_logbook_start(self):
t = localtime(self.start)
return "/logbook/date/%i/%i/%i" % (t.year, t.month, t.day)
def get_absolute_url_logbook_stop(self):
t = localtime(self.stop)
return "/logbook/date/%i/%i/%i" % (t.year, t.month, t.day)
@property
def is_past_due(self):
return localtime() > self.stop
@property
def is_future(self):
return localtime() < self.start
@property
def is_current(self):
return (localtime() > self.start and localtime() < self.stop)
def __str__(self):
return self.experiment+': '+self.target
# //SRG Scan Template Request
# //Created by Pavel Gureev at 10-07-2018
# SCAN_AXIS=Z // Z or Y
# SPAN=+5.0 // deg
# STEP=+0.1 // deg
# N_PASS=26 // 1 pass is 2*SPAN+2*STEP
# SPEED=0.0017 // deg/s
#class Template(models.Model):
# AXIS_CHOICES = (
# ('Z', 'Z axis'),
# ('Y', 'Y axis'),
# )
# scan_axis = models.CharField(max_length=1, choices=AXIS_CHOICES, help_text='Z or Y')
# span = models.FloatField(default=0.0, help_text='deg')
# step = models.FloatField(default=0.0, help_text='deg')
# n_pass = models.IntegerField(default=0, help_text='1 pass is 2*SPAN+2*STEP')
# speed = models.FloatField(default=0.0, help_text='deg/s')
# ref = models.IntegerField(default=0, help_text='reference number')
# [scan]
# // Work #1 for dd.mm.yyyy - Scan
# // Scan Template NNN based on Template Request MMM
# // Template duration is HH hours
# // SCAN_AXIS=Z, SPAN=zX.Xdeg, STEP=zY.YYdeg, N_PASS=PP, SPEED=X.XXXXdeg/s
# GUID = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# EXPERIMENT = AAAAAAAAA
# RA = XXX.XXXXXXXX // J2000
# DEC = zYY.YYYYYYYY // J2000
# START = dd.mm.yyyy hh:mm:ss
# STOP = dd.mm.yyyy hh:mm:ss
# ROLL_ANGLE = zXXX.X // Reference value
# SUN_XOZ_ANGLE = zXX.X
# TEMPLATE = XXX
class Scan(models.Model):
head = models.ForeignKey(Head, on_delete=models.CASCADE)
guid = models.CharField(max_length=36)
experiment = models.CharField(max_length=11)
target = models.CharField(max_length=50, default='')
ra = models.FloatField(default=0.0)
dec = models.FloatField(default=0.0)
start = models.DateTimeField(blank=True)
stop = models.DateTimeField(blank=True)
roll_angle = models.FloatField(default=0.0)
sun_xoz_angle = models.FloatField(default=0.0)
#template = models.ForeignKey(Template, on_delete=models.CASCADE)
template = models.IntegerField(default=0)
row = models.IntegerField(default=0)
ra_obj = models.FloatField(default=0.0)
dec_obj = models.FloatField(default=0.0)
name_obj = models.CharField(max_length=30, default='')
def get_absolute_url(self):
return "/monthplan/%i/getscan" % (self.pk)
def get_download_csv_url(self):
return "/monthplan/%i/getscan_csv" % (self.pk)
def get_absolute_url_logbook_start(self):
t = localtime(self.start)
return "/logbook/date/%i/%i/%i" % (t.year, t.month, t.day)
def get_absolute_url_logbook_stop(self):
t = localtime(self.stop)
return "/logbook/date/%i/%i/%i" % (t.year, t.month, t.day)
@property
def is_past_due(self):
return localtime() > self.stop
@property
def is_future(self):
return localtime() < self.start
@property
def is_current(self):
return (localtime() > self.start and localtime() < self.stop)
def __str__(self):
return self.experiment+': '+self.target
class ScanPath(models.Model):
scan = models.ForeignKey(Scan, on_delete=models.CASCADE)
dtime = models.DateTimeField(blank=True)
obt = models.FloatField(default=0.0)
eroday = models.FloatField(default=0.0)
mjd = models.FloatField(default=0.0)
ra = models.FloatField(default=0.0)
dec = models.FloatField(default=0.0)
roll = models.FloatField(default=0.0)
q1 = models.FloatField(default=0.0)
q2 = models.FloatField(default=0.0)
q3 = models.FloatField(default=0.0)
q4 = models.FloatField(default=0.0)
def __str__(self):
return "%s %.6f" % (self.scan.experiment, self.eroday)
# [survey]
# // Survey for January-April 2018
# GUID = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# EXPERIMENT = AAAAAAAAA
# START = dd.mm.yyyy hh:mm:ss
# STOP = dd.mm.yyyy hh:mm:ss // Reference value
# RA_P = XXX.XXXXX
# DEC_P = zXX.XXXXX
# RA_Z0 = XXX.XXXXX
# DEC_Z0 = +XX.XXXXX
# RA_ZK = XXX.XXXXX // Reference value
# DEC_ZK = zXX.XXXXX // Reference value
# Z_SPEED = X.XXXX // deg/day
class Survey(models.Model):
head = models.ForeignKey(Head, on_delete=models.CASCADE)
guid = models.CharField(max_length=36)
experiment = models.CharField(max_length=11)
target = models.CharField(max_length=50, default='')
start = models.DateTimeField(blank=True)
stop = models.DateTimeField(blank=True)
eroday_start = models.FloatField(default=0.0)
eroday_stop = models.FloatField(default=0.0)
mjd_start = models.FloatField(default=0.0)
mjd_stop = models.FloatField(default=0.0)
ra_p = models.FloatField(default=0.0)
dec_p = models.FloatField(default=0.0)
ra_z0 = models.FloatField(default=0.0)
dec_z0 = models.FloatField(default=0.0)
ra_zk = models.FloatField(default=0.0)
dec_zk = models.FloatField(default=0.0)
z_speed = models.FloatField(default=0.0, help_text='deg/day')
row = models.IntegerField(default=0)
loaded = models.BooleanField(default=False)
def get_path_filtered(self):
return self.surveypath_set.all()
def get_absolute_url(self):
t = localtime(self.start)
return "/monthplan/%i/getsurvey" % (self.pk)
def get_absolute_url_logbook_start(self):
t = localtime(self.start)
return "/logbook/date/%i/%i/%i" % (t.year, t.month, t.day)
def get_absolute_url_logbook_stop(self):
t = localtime(self.stop)
return "/logbook/date/%i/%i/%i" % (t.year, t.month, t.day)
@property
def is_past_due(self):
return localtime() > self.stop
@property
def is_future(self):
return localtime() < self.start
@property
def is_current(self):
return (localtime() > self.start and localtime() < self.stop)
def __str__(self):
return self.experiment
class SurveyPath(models.Model):
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
dtime = models.DateTimeField(blank=True)
obt = models.FloatField(default=0.0)
eroday = models.FloatField(default=0.0)
mjd = models.FloatField(default=0.0)
ra = models.FloatField(default=0.0)
dec = models.FloatField(default=0.0)
roll = models.FloatField(default=0.0)
q1 = models.FloatField(default=0.0)
q2 = models.FloatField(default=0.0)
q3 = models.FloatField(default=0.0)
q4 = models.FloatField(default=0.0)
class Meta:
ordering = ['obt']
def __str__(self):
return "%s %.6f" % (self.survey.experiment, self.eroday)
NSIDE_PLATES=32
NSIDE_SUBPLATES=256
ORDER='nested'
MAPS_DIR='/data/srg/eRosita/plates/'
class SurveyHealpixPlate(models.Model):
healpix = models.BigIntegerField(db_index=True, default=0)
ra = models.FloatField(default=0.0)
dec = models.FloatField(default=0.0)
survey = models.ManyToManyField('Survey')
def __str__(self):
return "HealpixPlate %s" % (self.healpix)
class SurveyHealpixSubPlate(models.Model):
plate = models.ForeignKey(SurveyHealpixPlate, on_delete=models.CASCADE)
healpix = models.BigIntegerField(db_index=True, default=0)
ra = models.FloatField(default=0.0)
dec = models.FloatField(default=0.0)
def __str__(self):
return "HealpixSubPlate %s" % (self.healpix)
# [seance]
# // Ground contact for dd.mm.yyyy
# GUID = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# START = dd.mm.yyyy hh:mm:ss
# STOP = dd.mm.yyyy hh:mm:ss
# STATIONS = station1, station2
class Seance(models.Model):
head = models.ForeignKey(Head, on_delete=models.CASCADE)
guid = models.CharField(max_length=36)
start = models.DateTimeField(blank=True)
stop = models.DateTimeField(blank=True)
stations = models.CharField(max_length=36)
row = models.IntegerField(default=0)
def get_absolute_url_logbook_start(self):
t = localtime(self.start)
return "/logbook/date/%i/%i/%i" % (t.year, t.month, t.day)
def get_absolute_url_logbook_stop(self):
t = localtime(self.stop)
return "/logbook/date/%i/%i/%i" % (t.year, t.month, t.day)
@property
def is_past_due(self):
return localtime() > self.stop
@property
def is_future(self):
return localtime() < self.start
@property
def is_current(self):
return (localtime() > self.start and localtime() < self.stop)
# [correction]
# // Orbital correction for dd.mm.yyyy
# GUID = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# START = dd.mm.yyyy hh:mm:ss
# STOP = dd.mm.yyyy hh:mm:ss
# IMPSTART = dd.mm.yyyy hh:mm:ss
class Correction(models.Model):
head = models.ForeignKey(Head, on_delete=models.CASCADE)
guid = models.CharField(max_length=36)
start = models.DateTimeField(blank=True)
stop = models.DateTimeField(blank=True)
impstart = models.DateTimeField(blank=True)
row = models.IntegerField(default=0)
@property
def is_past_due(self):
return date.today() > date(self.stop.year, self.stop.month, self.stop.day)
@property
def is_future(self):
return date.today() < date(self.start.year, self.start.month, self.start.day)
@property
def is_current(self):
return (date.today() > date(self.start.year, self.start.month, self.start.day) and date.today() < date(self.stop.year, self.stop.month, self.stop.day))
class DataDump(models.Model):
name = models.CharField(max_length=36)
start = models.DateTimeField(blank=True,null=True)
stop = models.DateTimeField(blank=True,null=True)
tstart = models.BigIntegerField(default=0)
tstop = models.BigIntegerField(default=0)
path = models.CharField(max_length=120)
filename = models.CharField(max_length=50)
mjd_start = models.FloatField(default=0.0)
mjd_stop = models.FloatField(default=0.0)
observations = models.ManyToManyField('Observation')
scans = models.ManyToManyField('Scan')
def __str__(self):
return self.name

View File

View File

@@ -0,0 +1,29 @@
from django import template
register = template.Library()
@register.filter(name='has_group')
def has_group(user, group_name):
return user.groups.filter(name=group_name).exists()
@register.filter
def next(some_list, current_index):
"""
Returns the next element of the list using the current index if it exists.
Otherwise returns an empty string.
"""
try:
return some_list[int(current_index) + 1] # access the next element
except:
return '' # return empty string in case of exception
@register.filter
def previous(some_list, current_index):
"""
Returns the previous element of the list using the current index if it exists.
Otherwise returns an empty string.
"""
try:
return some_list[int(current_index) - 1] # access the previous element
except:
return '' # return empty string in case of exception

3
monthplan/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

44
monthplan/urls.py Normal file
View File

@@ -0,0 +1,44 @@
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='monthplan index'),
path('scans', views.show_scans, name="list of scans"),
path('surveys', views.show_surveys, name="list of surveys"),
path('observations', views.show_observations, name="list of observations"),
path('time', views.time, name="AJAX time"),
path('wherenow', views.wherenow, name="AJAX currently observing"),
path('admin', views.index_admin, name='index_admin'),
path('load', views.load_monthplan, name='load plan'),
path('flightplan', views.index_flightplan, name='index_pz'),
path('tracking', views.show_tracking, name='tracking'),
path('flightplan/valid', views.index_flightplan_valid, name='index_pz'),
path('flightplan/invalid', views.index_flightplan_invalid, name='index_pz'),
path('<int:monthplan_id>', views.show_monthplan, name='show monthplan'),
path('<int:monthplan_id>/table', views.show_monthplan_table, name='show monthplan'),
path('<int:monthplan_id>/aladin', views.show_monthplan_aladin, name='show aladin'),
path('<int:monthplan_id>/seance', views.show_monthplan_seance, name='show monthplan seance'),
path('<int:monthplan_id>/share', views.share_monthplan, name='share monthplan'),
path('<int:monthplan_id>/observation', views.show_monthplan_observation, name='show monthplan seance'),
path('<int:observation_id>/getobs', views.show_observation_info, name='show observation info'),
path('<int:flightplan_id>/getpz', views.show_flightplan_info, name='show flight info'),
path('<int:scan_id>/getscan', views.show_scan_info, name='show scan info'),
path('<int:scan_id>/getscan_csv', views.scan_download_csv, name='download scan csv'),
path('<int:survey_id>/getsurvey', views.show_survey_info, name='show survey info'),
path('<int:monthplan_id>/scan', views.show_monthplan_scan, name='show monthplan seance'),
path('<int:monthplan_id>/survey', views.show_monthplan_survey, name='show monthplan survey'),
path('<int:monthplan_id>/correction', views.show_monthplan_correction, name='show monthplan seance'),
path('<int:monthplan_id>/delete', views.delete_monthplan, name='delete monthplan'),
path('upload', views.upload, name='upload month plan'),
path('obsid', views.get_obsid_search, name='get_obsid_search'),
#path('day/<int:day_id>/update', views.update, name='update'),
#path('day/<int:day_id>/upload/<int:upload_id>/delete', views.delete_upload, name='delete'),
#path('day/<int:day_id>', views.show_day, name='show'),
#path('login', views.login_username, name='login'),
#path('logout', views.logout_view, name='logout'),
#path('uploads', views.show_uploads, name='uploads'),
#path('info', views.show_info, name='info'),
#path('category/<int:category_id>/show', views.show_category, name='showCategory'),
]

275
monthplan/utils.py Normal file
View File

@@ -0,0 +1,275 @@
import numpy as np
from math import pi, cos, sin
from Quaternion import Quat
from dateutil.parser import parse
from datetime import timedelta
import glob
import re
import fnmatch
import os
import logging
from scipy.spatial.transform import Rotation, Slerp
import pandas as pd
from pandas import ExcelWriter
from pandas import ExcelFile
from astropy_healpix import HEALPix
from astropy import units as u
from astropy.coordinates import SkyCoord, RangeError
from astropy.coordinates import ICRS, Galactic, FK5
from astropy.coordinates import Angle
import astropy.units as u
from astropy.time.formats import erfa
from astropy.time import Time, TimeDelta, TimezoneInfo, TimeFromEpoch
from astropy.io import fits
from astropy.table import Table
from django.contrib.auth.models import User
from django.core import mail
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.core.mail import send_mail
from monthplan.models import Survey, SurveyPath, NSIDE_PLATES, ORDER, SurveyHealpixPlate
from monthplan.models import Head, Observation, Seance, Correction, Scan
from srglib.utils import date2mission, slerp, str2date, TZ_MSK
#MJDREF = 51543.875
#TZ_UTC = TimezoneInfo(utc_offset=0*u.hour)
#TZ_MSK = TimezoneInfo(utc_offset=3*u.hour)
def logic(index,nskip):
if index % nskip == 0:
return False
return True
def load_surveypath_data(file, nskip=100, forced=False, notify=False):
match = '20??????_??????_???????????.iki'
filename=os.path.basename(file)
if fnmatch.fnmatch(filename, match):
logging.debug("Match filename: Read {}".format(file))
else:
logging.debug("Match filename: Skip {}".format(file))
obsid = re.findall("\d+", file)[2]
if(obsid == '11000400200'):
"""
Merge two files for 11000400200:
cat
/mnt/nfs/npol/orientation/DMV/ARJ-SCAN/20200218_220000_11000300500.iki
/mnt/nfs/npol/orientation/DMV/ARJ-SCAN/20200219_180000_11000400200.iki
> /srv/srg-plan/srg/data/ARJ-SCAN/20200219_180000_11000400200.actual.iki
"""
file='/export/django/srg/data/npol/ARJ-SCAN/20200219_180000_11000400200.actual.iki'
logging.debug("Special case for 11000400200, load correct file {}".format(file))
try:
survey=Survey.objects.get(experiment__exact=obsid)
except:
logging.debug("Survey {} is not found".format(obsid))
return
""" Update eroday start/stop """
survey.eroday_start=date2mission(survey.start)/14400
survey.eroday_stop=date2mission(survey.stop)/14400
survey.mjd_start = Time(survey.start , format='datetime').mjd
survey.mjd_stop = Time(survey.stop , format='datetime').mjd
survey.save()
if(forced == True):
survey.loaded=False
survey.save()
if(survey.loaded == True):
logging.debug("Survey {} is already loaded, skip.".format(obsid))
return
logging.info("Load {}, for Survey {}".format(file,obsid))
spath=survey.surveypath_set.all()
spath.delete()
csvfile=file
df = pd.read_csv(csvfile,names=['date', 'time', 'q1', 'q2','q3','q4','dummy'], header=None, delim_whitespace=True, skipfooter=1, engine='python', skiprows = lambda x: logic(x, nskip))
for i in df.index:
dtstr="%s %s" % (df['date'][i], df['time'][i])
dt = str2date(dtstr, tzone=TZ_MSK)
ts = date2mission(dt)
eroday=ts/14400
dtime = Time(dt , format='datetime')
mjd=dtime.mjd
q1=df['q1'][i]
q2=df['q2'][i]
q3=df['q3'][i]
q4=df['q4'][i]
quat=Quat(attitude=[q2,q3,q4,q1])
sp=SurveyPath(survey=survey,dtime=dt,mjd=mjd,obt=ts,eroday=eroday,q1=q1,q2=q2,q3=q3,q4=q4,ra=quat.ra,dec=quat.dec,roll=quat.roll)
sp.save()
survey.loaded=True
""" Mark survey as loaded """
survey.save()
tolerance=10
hp = HEALPix(nside=NSIDE_PLATES, order=ORDER, frame=FK5())
surveypaths = survey.surveypath_set.all()
for i in range(len(surveypaths)-1):
delta=(surveypaths[i+1].dtime-surveypaths[i].dtime).total_seconds()
if(abs(int(delta)) > tolerance):
nstep = int(abs(delta) / tolerance)
delta_arr = np.linspace(0,1,nstep)
quat = slerp([surveypaths[i].q2, surveypaths[i].q3, surveypaths[i].q4, surveypaths[i].q1],
[surveypaths[i+1].q2, surveypaths[i+1].q3, surveypaths[i+1].q4, surveypaths[i+1].q1],
delta_arr)
for q in quat:
qfin=Quat(attitude=q)
crd = SkyCoord(qfin.ra, qfin.dec, frame="fk5", unit="deg")
heal = hp.skycoord_to_healpix(crd)
try:
plate = SurveyHealpixPlate.objects.get(healpix=heal)
except:
logging.error('Error: SurveyHealpixPlate not found, run ./manage.py init_survey_healpix_plates first')
break
queryset = survey.surveyhealpixplate_set.all()
if not queryset.filter(pk=plate.pk).exists():
plate.survey.add(survey)
plate.save()
if(notify == True):
users = User.objects.filter(groups__name='srg-iki-admin')
to_emails=[]
for user in users:
to_emails.append(user.email)
subject = "SRG-ArXiv: New SRG flight plan {}".format(obsid)
html_message = render_to_string('monthplan/surveypath_loaded_email.html', {'survey':survey,})
plain_message = strip_tags(html_message)
from_email = 'Roman Krivonos <krivonos@cosmos.ru>'
for email in to_emails:
mail.send_mail(subject, plain_message, from_email, [email], html_message=html_message)
def load_monthplan_fits(filename):
table = Table.read(filename)
df = table.to_pandas()
#print("Column headings:")
#print(df.columns.str.encode('utf-8'))
hdul = fits.open(filename)
#hdul.info()
version=int(hdul[1].header['VERSION'])
""" delete existing month plan at this month """
dt = parse(hdul[1].header['START'])
middle=dt+timedelta(days=10)
heads = Head.objects.all()
for h in heads:
dt = h.get_datetime()
if(dt.year == middle.year and dt.month == middle.month):
print("Found {} v{} (new v{})".format(h,h.version,version))
if(h.version < version):
print("Delete {} v{} (new v{})".format(h,h.version,version))
h.delete()
else:
print("Skip loading, already exists: {} v{}".format(h,h.version))
return
print("Loading ",filename)
head=Head()
head.start=hdul[1].header['START']
head.stop=hdul[1].header['STOP']
head.gentime=hdul[1].header['GENTIME']
head.version=hdul[1].header['VERSION']
head.author=hdul[1].header['AUTHOR']
head.file=os.path.basename(filename)
head.nrows=df.shape[0]
head.save()
for i in df.index:
row=(i+1)
if(df['TYPE'][i].decode().strip() == 'SEANCE'):
""" print(df['START'][i].decode().strip()) """
seance=Seance(head=head, row=row)
seance.start=df['START'][i].decode().strip()
seance.stop=df['STOP'][i].decode().strip()
seance.stations=df['STATIONS'][i].decode().strip()
seance.guid=df['GUID'][i].decode().strip()
seance.save()
if(df['TYPE'][i].decode().strip() == 'OBSERVATION'):
obs=Observation(head=head, row=row)
obs.start=df['START'][i].decode().strip()
obs.stop=df['STOP'][i].decode().strip()
obs.target=df['TARGET'][i].decode().strip()
obs.experiment=df['EXPERIMENT'][i].decode().strip()
obs.ra=df['RA'][i]
obs.dec=df['DEC'][i]
obs.ra=df['RA'][i]
obs.roll_angle=df['ROLL_ANGLE'][i]
obs.sun_xoz_angle=df['SUN_XOZ_ANGLE'][i]
obs.guid=df['GUID'][i].decode().strip()
obs.save()
if(df['TYPE'][i].decode().strip() == 'CORRECTION'):
cor=Correction(head=head, row=row)
cor.start=df['START'][i].decode().strip()
cor.stop=df['STOP'][i].decode().strip()
cor.impstart=df['IMPSTART'][i].decode().strip()
cor.guid=df['GUID'][i].decode().strip()
cor.save()
if(df['TYPE'][i].decode().strip() == 'SCAN'):
scan=Scan(head=head, row=row)
scan.start=df['START'][i].decode().strip()
scan.stop=df['STOP'][i].decode().strip()
scan.target=df['TARGET'][i].decode().strip()
scan.experiment=df['EXPERIMENT'][i].decode().strip()
scan.ra=df['RA'][i]
scan.dec=df['DEC'][i]
scan.roll_angle=df['ROLL_ANGLE'][i]
scan.sun_xoz_angle=df['SUN_XOZ_ANGLE'][i]
scan.template=int(df['TEMPLATE'][i].decode().strip())
scan.guid=df['GUID'][i].decode().strip()
scan.save()
if(df['TYPE'][i].decode().strip() == 'SURVEY'):
sur=Survey(head=head, row=row)
sur.start=df['START'][i].decode().strip()
sur.stop=df['STOP'][i].decode().strip()
sur.target=df['TARGET'][i].decode().strip()
sur.experiment=df['EXPERIMENT'][i].decode().strip()
sur.ra_p=df['RA_P'][i]
sur.dec_p=df['DEC_P'][i]
sur.ra_z0=df['RA_Z0'][i]
sur.dec_z0=df['DEC_Z0'][i]
sur.ra_zk=df['RA_ZK'][i]
sur.dec_zk=df['DEC_ZK'][i]
sur.z_speed=df['Z_SPEED'][i]
sur.guid=df['GUID'][i].decode().strip()
sur.save()
def load_monthplan_dir(dir):
""" Loads monthplan from dir
Parameters
----------
dir : str
Absolute path to the input directory
:Author:
Roman Krivonos <krivonos@cosmos.ru>
"""
# /export/django/srg/data/npol/fits/RG_MonthPlan_2020-06_v07.fits
logging.info("Loading monthplan from {}".format(dir))
files = glob.glob("{}/RG_MonthPlan_202?-??_v??.fits".format(dir))
files.sort(key=os.path.getmtime)
for filename in files:
#print(filename)
load_monthplan_fits(filename)

553
monthplan/views.py Normal file
View File

@@ -0,0 +1,553 @@
from django.shortcuts import render
from monthplan.models import Head
from monthplan.models import Observation, Seance, Correction, Scan
from monthplan.models import Survey, MonthPlanUpload, MonthPlanUploadForm
from monthplan.models import FlightPlan, DataDump, ScanPath
from monthplan.forms import ObsIDSearchForm
from plan.models import LaunchDate
from datetime import datetime as dt
from django.utils import timezone
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.http import HttpResponseForbidden
import csv
from django.utils.encoding import smart_str
from django.contrib.auth.models import User
from django.core.mail import send_mail
import pandas as pd
from astropy.table import Table
from astropy.io import fits
import math
from Quaternion import Quat
from django.http import JsonResponse
from django.db.models import Q
def find_closest(now, closest_greater_qs, closest_less_qs):
try:
try:
closest_greater = closest_greater_qs[0]
except IndexError:
closest = closest_less_qs[0]
try:
closest_less = closest_less_qs[0]
except IndexError:
closest = closest_greater_qs[0]
except IndexError:
raise self.model.DoesNotExist("There is no closest object"
" because there are no objects.")
if closest_greater.dtime - now > now - closest_less.dtime:
closest = closest_less
else:
closest = closest_greater
return closest.ra, closest.dec
# Create your views here.
def time(request):
""" AJAX time procedure """
now = timezone.localtime(timezone.now())
data = {
'time': now.strftime('%d %b %Y %H:%M:%S MSK'),
}
return JsonResponse(data)
def wherenow(request):
request_path = request.GET.get('request_path', None)
now = timezone.localtime(timezone.now()) # timezone.now() # dt.now()
target = 'None'
obsid = 'None'
url = '#'
ra = 'n/a'
dec = 'n/a'
mode=''
msg=''
path=list()
try:
#surveys=Survey.objects.filter(experiment__contains="10000100100")
surveys = Survey.objects.filter(Q(start__lte=now) & Q(stop__gte=now))
# take first element only:
for survey in surveys:
target = survey.target
obsid = survey.experiment
url = survey.get_absolute_url()
ra="%.4f" % survey.ra_p
dec="%.4f" % survey.dec_p
mode='Survey'
"""
if request_path == "load":
path=list(survey.surveypath_set.all().values('ra', 'dec'))[::200]
"""
closest_greater_qs = survey.surveypath_set.filter(dtime__gt=now).order_by('dtime')
closest_less_qs = survey.surveypath_set.filter(dtime__lt=now).order_by('-dtime')
closest_ra, closest_dec = find_closest(now, closest_greater_qs, closest_less_qs)
ra="%.4f" % closest_ra
dec="%.4f" % closest_dec
break
except NameError as error:
pass
try:
scans = Scan.objects.filter(Q(start__lte=now) & Q(stop__gte=now))
# take first element only
for scan in scans:
target = scan.target
obsid = scan.experiment
url = scan.get_absolute_url()
ra="%.4f" % scan.ra
dec="%.4f" % scan.dec
mode='Scan'
if request_path == "load":
path=list(scan.scanpath_set.all().values('ra', 'dec'))[::50]
closest_greater_qs = scan.scanpath_set.filter(dtime__gt=now).order_by('dtime')
closest_less_qs = scan.scanpath_set.filter(dtime__lt=now).order_by('-dtime')
try:
try:
closest_greater = closest_greater_qs[0]
except IndexError:
closest = closest_less_qs[0]
try:
closest_less = closest_less_qs[0]
except IndexError:
closest = closest_greater_qs[0]
except IndexError:
raise self.model.DoesNotExist("There is no closest object"
" because there are no objects.")
if closest_greater.dtime - now > now - closest_less.dtime:
closest = closest_less
else:
closest = closest_greater
# update ra, dec
ra="%.4f" % closest.ra
dec="%.4f" % closest.dec
break
except NameError as error:
pass
try:
observations = Observation.objects.filter(Q(start__lte=now) & Q(stop__gte=now))
# take first element only:
for obs in observations:
target = obs.target
obsid = obs.experiment
url = obs.get_absolute_url()
ra="%.4f" % obs.ra
dec="%.4f" % obs.dec
mode='Pointing'
break
except NameError as error:
pass
data = {
'time': now.strftime('%d %b %Y %H:%M:%S MSK'),
'target': target,
'obsid': obsid,
'url': url,
'msg': msg,
'ra': ra, 'dec': dec,
#'observations': list(observations.values()) ,
#'scans': list(scans.values()) ,
#'surveys': list(surveys.values()),
'path':path,
'mode':mode,
}
return JsonResponse(data)
def index(request):
heads = Head.objects.all().order_by('-start')
return render(request,'monthplan/index.html', {'heads': heads,'today':dt.now(),})
def index_flightplan(request):
flightplans = FlightPlan.objects.all()
return render(request,'monthplan/index_flightplan.html', {'flightplans': flightplans,'today':dt.now(),})
def index_flightplan_valid(request):
flightplans = FlightPlan.objects.filter(valid__exact=True)
return render(request,'monthplan/index_flightplan.html', {'flightplans': flightplans,'today':dt.now(),})
def index_flightplan_invalid(request):
flightplans = FlightPlan.objects.filter(valid__exact=False)
return render(request,'monthplan/index_flightplan.html', {'flightplans': flightplans,})
def index_admin(request):
heads = Head.objects.all()
return render(request,'monthplan/index.html', {'heads': heads,'admin':True,})
def show_scans(request):
scans = Scan.objects.all().order_by('start')
return render(request,'monthplan/show_targets.html', {'scans':scans,})
def show_surveys(request):
surveys = Survey.objects.all().order_by('start')
return render(request,'monthplan/show_targets.html', {'surveys':surveys,})
def show_observations(request):
observations = Observation.objects.all().order_by('start')
return render(request,'monthplan/show_targets.html', {'observations': observations,})
def load_monthplan(request):
heads = Head.objects.all()
return render(request,'monthplan/index.html', {'heads': heads,'admin':True,})
def show_monthplan(request, monthplan_id):
try:
head=Head.objects.get(pk=monthplan_id)
except:
return HttpResponse("This month plan was not found")
seances = head.seance_set.all()
observations = head.observation_set.all()
corrections = head.correction_set.all()
scans = head.scan_set.all()
surveys = head.survey_set.all()
seq = range(1,head.nrows+1)
return render(request,'monthplan/show_monthplan.html', {'head': head,
'seances':seances,
'observations':observations,
'corrections':corrections,
'scans':scans,
'surveys':surveys,
'seq':seq,
'today':dt.now(),})
def share_monthplan(request, monthplan_id):
try:
head=Head.objects.get(pk=monthplan_id)
except:
return HttpResponse("This month plan was not found")
seances = head.seance_set.all()
observations = head.observation_set.all()
corrections = head.correction_set.all()
scans = head.scan_set.all()
surveys = head.survey_set.all()
seq = range(1,head.nrows+1)
emails = []
users = User.objects.all()
for user in users:
emails.append(user.email)
mid=head.get_datetime()
email_subject = "SRG-IKI month plan for %s" % (mid.strftime("%B %Y"))
email_body = u"The following SRG month plan for %s has been added/updated: http://193.232.10.38/%s\n\nThis SRG-IKI service email is sent to all registered users on srg.cosmos.ru. This is an automatic email, please do not reply. If you do not want to receive this kind of notifications, please drop a message to Roman Krivonos (krivonos@cosmos.ru)." % (mid.strftime("%B %Y"), head.get_absolute_url())
for email in emails:
send_mail(email_subject,email_body,'krivonos@cosmos.ru',[email])
return render(request,'monthplan/show_monthplan.html', {'head': head,
'seances':seances,
'observations':observations,
'corrections':corrections,
'scans':scans,
'surveys':surveys,
'seq':seq,
'today':dt.now(),})
def show_monthplan_table(request, monthplan_id):
try:
head=Head.objects.get(pk=monthplan_id)
except:
return HttpResponse("This month plan was not found")
seances = head.seance_set.all()
observations = head.observation_set.all()
corrections = head.correction_set.all()
scans = head.scan_set.all()
surveys = head.survey_set.all()
seq = range(1,head.nrows+1)
return render(request,'monthplan/show_monthplan_table.html', {'head': head,
'seances':seances,
'observations':observations,
'corrections':corrections,
'scans':scans,
'surveys':surveys,
'seq':seq,
'today':dt.now(),})
def show_monthplan_aladin(request, monthplan_id):
try:
head=Head.objects.get(pk=monthplan_id)
except:
return HttpResponse("This month plan was not found")
seances = head.seance_set.all()
observations = head.observation_set.all()
corrections = head.correction_set.all()
scans = head.scan_set.all()
surveys = head.survey_set.all()
surveypaths = []
for survey in surveys:
surveypaths.extend(list(survey.surveypath_set.all().order_by('obt')))
seq = range(1,head.nrows+1)
return render(request,'monthplan/show_monthplan_aladin.html', {'surveypaths':surveypaths, 'head': head,
'seances':seances,
'observations':observations,
'corrections':corrections,
'scans':scans,
'surveys':surveys,
'seq':seq,
'today':dt.now(),})
def delete_monthplan(request, monthplan_id):
try:
head=Head.objects.get(pk=monthplan_id)
except:
return HttpResponse("This month plan was not found")
#head.upload.delete()
head.delete()
heads = Head.objects.all()
return render(request,'monthplan/index.html', {'heads': heads,'today':dt.now(),'admin':True,})
def show_observation_info(request, observation_id):
try:
observation=Observation.objects.get(pk=observation_id)
except Observation.DoesNotExist:
return HttpResponseRedirect('/monthplan')
flightplans=FlightPlan.objects.filter(experiment__contains=observation.experiment)
datadumps=observation.datadump_set.all()
return render(request,'monthplan/show_observation_info.html', {'head': observation.head, 'observation': observation,'flightplans':flightplans,'datadumps':datadumps,'today':dt.now(),})
def show_flightplan_info(request, flightplan_id):
try:
pz=FlightPlan.objects.get(pk=flightplan_id)
except FlightPlan.DoesNotExist:
return HttpResponseRedirect('/monthplan')
observations=Observation.objects.filter(experiment__exact=pz.experiment)
scans=Scan.objects.filter(experiment__exact=pz.experiment)
surveys=Survey.objects.filter(experiment__exact=pz.experiment)
return render(request,'monthplan/show_flightplan_info.html', {'observations': observations, 'scans':scans, 'surveys':surveys, 'obs':pz, 'today':dt.now(),})
def show_scan_info(request, scan_id):
try:
scan=Scan.objects.get(pk=scan_id)
except Scan.DoesNotExist:
return HttpResponseRedirect('/monthplan')
flightplans=FlightPlan.objects.filter(experiment__contains=scan.experiment)
datadumps=scan.datadump_set.all()
scanpaths=scan.scanpath_set.all()
return render(request,'monthplan/show_scan_info.html', {'head':scan.head, 'scan': scan,'flightplans':flightplans,'scanpaths':scanpaths,'datadumps':datadumps,'today':dt.now(),})
def scan_download_csv(request, scan_id):
try:
scan=Scan.objects.get(pk=scan_id)
except Scan.DoesNotExist:
return HttpResponseRedirect('/monthplan')
scanpaths=scan.scanpath_set.all()#[::50]
response = HttpResponse(content_type='text/csv')
#decide the file name
response['Content-Disposition'] = 'attachment; filename='+"scan_%s.csv" % (scan.experiment,)
writer = csv.writer(response, csv.excel)
#response.write(u'\ufeff'.encode('utf8'))
response.write(u'# '.encode('utf8'))
#write the headers
writer.writerow([
smart_str(u"MJD"),
smart_str(u"EroDay"),
smart_str(u"RA"),
smart_str(u"Dec"),
])
for path in scanpaths:
writer.writerow([
smart_str(path.mjd),
smart_str(path.eroday),
smart_str(path.ra),
smart_str(path.dec),
])
return response
# fsock = open('/path/to/file.mp3', 'r')
# response = HttpResponse(fsock, content_type='audio/mpeg')
# response['Content-Disposition'] = "attachment; filename=%s - %s.mp3" % \
# (song.artist, song.title)
# return response
def show_tracking(request):
return render(request,'monthplan/show_tracking.html')
def show_survey_info(request, survey_id):
try:
survey=Survey.objects.get(pk=survey_id)
except Survey.DoesNotExist:
return HttpResponseRedirect('/monthplan')
flightplans=FlightPlan.objects.filter(experiment__contains=survey.experiment)
surveypaths=survey.surveypath_set.all().order_by('obt')
plates = survey.surveyhealpixplate_set.all().order_by('healpix')
return render(request,'monthplan/show_survey_info.html', {'head':survey.head, 'surveypaths':surveypaths, 'survey': survey,'flightplans':flightplans,'plates':plates,'today':dt.now(),})
def show_monthplan_seance(request, monthplan_id):
try:
head=Head.objects.get(pk=monthplan_id)
except:
return HttpResponseRedirect('/monthplan')
seances = head.seance_set.all()
return render(request,'monthplan/show_monthplan.html', {'head': head,'seances':seances,'today':dt.now(),})
def show_monthplan_observation(request, monthplan_id):
try:
head=Head.objects.get(pk=monthplan_id)
except Head.DoesNotExist:
return HttpResponseRedirect('/monthplan')
observations = head.observation_set.all()
return render(request,'monthplan/show_monthplan.html', {'head': head,'observations':observations,'today':dt.now(),})
def show_monthplan_correction(request, monthplan_id):
try:
head=Head.objects.get(pk=monthplan_id)
except:
return HttpResponseRedirect('/monthplan')
corrections = head.correction_set.all()
return render(request,'monthplan/show_monthplan.html', {'head': head,'corrections':corrections,'today':dt.now(),})
def show_monthplan_scan(request, monthplan_id):
try:
head=Head.objects.get(pk=monthplan_id)
except:
return HttpResponseRedirect('/monthplan')
scans = head.scan_set.all()
return render(request,'monthplan/show_monthplan.html', {'head': head,'scans':scans,'today':dt.now(),})
def show_monthplan_survey(request, monthplan_id):
try:
head=Head.objects.get(pk=monthplan_id)
except:
return HttpResponseRedirect('/monthplan')
surveys = head.survey_set.all()
return render(request,'monthplan/show_monthplan.html', {'head': head,'surveys':surveys,'today':dt.now(),})
def upload(request):
if not request.user.is_authenticated:
html = "<html><body>You have no rights for this operation.</body></html>"
return HttpResponseForbidden(html)
try:
user_profile=request.user.profile
except:
html = "<html><body>You have no user profile.</body></html>"
return HttpResponseForbidden(html)
if request.method == 'POST':
form = MonthPlanUploadForm(request.POST, request.FILES)
if form.is_valid():
upload = form.save(commit=False)
upload.owner = user_profile
upload.filename = request.FILES['filefield'].name.encode('utf-8')
upload.save()
table = Table.read(upload.filefield.path)
df = table.to_pandas()
hdul = fits.open(upload.filefield.path)
hdul.info()
head=Head()
head.title=upload.title
head.start=hdul[1].header['START']
head.stop=hdul[1].header['STOP']
head.gentime=hdul[1].header['GENTIME']
head.version=hdul[1].header['VERSION']
head.author=hdul[1].header['AUTHOR']
head.nrows=df.shape[0]
head.save()
upload.head=head
upload.save()
for i in df.index:
row=(i+1)
if(df['TYPE'][i].decode().strip() == 'SEANCE'):
print('SEA')
print(df['START'][i].decode().strip())
seance=Seance(head=head, row=row)
seance.start=df['START'][i].decode().strip()
seance.stop=df['STOP'][i].decode().strip()
seance.stations=df['STATIONS'][i].decode().strip()
seance.guid=df['GUID'][i].decode().strip()
seance.save()
if(df['TYPE'][i].decode().strip() == 'OBSERVATION'):
obs=Observation(head=head, row=row)
obs.start=df['START'][i].decode().strip()
obs.stop=df['STOP'][i].decode().strip()
obs.target=df['TARGET'][i].decode().strip()
obs.experiment=df['EXPERIMENT'][i].decode().strip()
obs.ra=df['RA'][i]
obs.dec=df['DEC'][i]
if('RA_OBJ' in df):
obs.ra_obj=df['RA_OBJ'][i]
if('DEC_OBJ' in df):
obs.dec_obj=df['DEC_OBJ'][i]
if('OBJECT' in df):
obs.name_obj=df['OBJECT'][i].decode().strip()
obs.roll_angle=df['ROLL_ANGLE'][i]
obs.sun_xoz_angle=df['SUN_XOZ_ANGLE'][i]
obs.guid=df['GUID'][i].decode().strip()
obs.save()
if(df['TYPE'][i].decode().strip() == 'CORRECTION'):
cor=Correction(head=head, row=row)
cor.start=df['START'][i].decode().strip()
cor.stop=df['STOP'][i].decode().strip()
cor.impstart=df['IMPSTART'][i].decode().strip()
cor.guid=df['GUID'][i].decode().strip()
cor.save()
if(df['TYPE'][i].decode().strip() == 'SCAN'):
print('SCAN')
scan=Scan(head=head, row=row)
scan.start=df['START'][i].decode().strip()
scan.stop=df['STOP'][i].decode().strip()
scan.target=df['TARGET'][i].decode().strip()
scan.experiment=df['EXPERIMENT'][i].decode().strip()
scan.ra=df['RA'][i]
scan.dec=df['DEC'][i]
scan.roll_angle=df['ROLL_ANGLE'][i]
scan.sun_xoz_angle=df['SUN_XOZ_ANGLE'][i]
scan.template=int(df['TEMPLATE'][i].decode().strip())
scan.guid=df['GUID'][i].decode().strip()
scan.save()
if(df['TYPE'][i].decode().strip() == 'SURVEY'):
sur=Survey(head=head, row=row)
sur.start=df['START'][i].decode().strip()
sur.stop=df['STOP'][i].decode().strip()
sur.target=df['TARGET'][i].decode().strip()
sur.experiment=df['EXPERIMENT'][i].decode().strip()
sur.ra_p=df['RA_P'][i]
sur.dec_p=df['DEC_P'][i]
sur.ra_z0=df['RA_Z0'][i]
sur.dec_z0=df['DEC_Z0'][i]
sur.ra_zk=df['RA_ZK'][i]
sur.dec_zk=df['DEC_ZK'][i]
sur.z_speed=df['Z_SPEED'][i]
sur.guid=df['GUID'][i].decode().strip()
sur.save()
return HttpResponseRedirect(head.get_absolute_url())
else:
form = MonthPlanUploadForm()
return render(request,'monthplan/upload.html',
{'UserProfile':user_profile, 'form': form,}
)
def get_obsid_search(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = ObsIDSearchForm(request.POST)
# check whether it's valid:
if form.is_valid():
obsid = form.cleaned_data['obsid']
observations=Observation.objects.filter(experiment__contains=obsid)
scans=Scan.objects.filter(experiment__contains=obsid)
surveys=Survey.objects.filter(experiment__contains=obsid)
flightplans=FlightPlan.objects.filter(experiment__contains=obsid)
#ordered=phots.order_by('separation')
return render(request, 'monthplan/obsid_search.html', {'form': form, 'observations':observations,'scans':scans,'surveys':surveys,'flightplans':flightplans,})
# if a GET (or any other method) we'll create a blank form
else:
form = ObsIDSearchForm()
#MyModel.objects.all().annotate(mycolumn=Value('xxx', output_field=CharField()))
return render(request, 'monthplan/obsid_search.html', {'form': form})