525 lines
20 KiB
Python
525 lines
20 KiB
Python
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
|