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