srg/monthplan/models.py
2024-04-26 12:43:00 +03:00

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