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

1286 lines
56 KiB
Python

from django.db import models
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.core.validators import MaxLengthValidator,MinValueValidator,MaxValueValidator
from math import isfinite, sqrt
import math
import time
from django.core.exceptions import PermissionDenied
import urllib.parse
from django.core.files.storage import FileSystemStorage
import hashlib
import sys, os, os.path as osp
from django.dispatch import receiver
from django import forms
from astropy import units as u
from astropy.coordinates import SkyCoord
from astropy.coordinates import ICRS, Galactic, FK5
from astropy.coordinates import BarycentricTrueEcliptic
from heasarc.models import HeasarcBase
from heasarc.models import HeasarcSwiftBAT105m
from heasarc.models import Heasarc4XMMDR9
from heasarc.models import HeasarcRASS2RXS
from heasarc.models import HeasarcIntRefCat
from heasarc.models import HeasarcSimpleClass
from heasarc.models import HeasarcUserCat
from astrobasis.models import GAIADR2
from astrobasis.models import GAIADR3
from astrobasis.models import Simbad
from astrobasis.models import AllWise
from astrobasis.models import NVSS
from astrobasis.models import FIRST
from astrobasis.models import SUMSS
from astrobasis.models import VLASS
from astrobasis.models import VLASSfromVizieR
from astrobasis.models import BJfromVizieR
from astrobasis.models import GAIADR3fromVizieR
from astropy.table import Table
from nasa.models import Ads
import numpy
FS = FileSystemStorage(location='/export/django/Uploads/artsurvey')
VALID_EXTENSIONS = ['.pdf', '.ppt', '.pptx', '.png','.csv', '.txt', '.dat', '.xlsx','.docx','.gz','.jpg','.jpeg','.gz','.fits.gz','.fits','.reg','.FTZ','.evt','.fz','.qdp',]
def validate_upload(value):
file = value.file
_, ext = osp.splitext(file.name)
if ext not in VALID_EXTENSIONS:
raise forms.ValidationError('Extension %s not supported.' % ext)
def upload_filename(instance, filename):
_, ext = osp.splitext(filename)
tohash = filename + str(time.clock())
#new_fname = hashlib.md5(tohash).hexdigest()
new_fname = hashlib.md5(tohash.encode('utf-8')).hexdigest()
return new_fname + ext
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField()
parent = models.ForeignKey('self',blank=True, null=True ,related_name='children', on_delete=models.CASCADE)
class Meta:
unique_together = ('slug', 'parent',) #enforcing that there can not be two
verbose_name_plural = "categories" #categories under a parent with same
#slug
def get_absolute_url(self):
return "/artsurvey/category/%i/show" % (self.pk)
def __str__(self): # __str__ method elaborated later in
full_path = [self.name] # post. use __unicode__ in place of
# __str__ if you are using python 2
k = self.parent
while k is not None:
full_path.append(k.name)
k = k.parent
return ' -> '.join(full_path[::-1])
class Catalog(models.Model):
""" General catalog class """
name = models.CharField(max_length=36)
#test = models.CharField(max_length=36,default='')
year = models.PositiveIntegerField(default=0)
def __str__(self):
return "{} ({})".format(self.name, self.year)
class MetaSource(models.Model):
"""
ArtSurvey MetaSource class
Dynamic information !!!
"""
catalog = models.ForeignKey(Catalog, null=True, blank=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=36)
healpix = models.BigIntegerField(db_index=True, default=0)
ra = models.FloatField(default=0.0)
dec = models.FloatField(default=0.0)
def __str__(self):
return "{} ({})".format(self.name, self.year)
glon = models.FloatField(default=0.0)
glat = models.FloatField(default=0.0)
elon = models.FloatField(default=0.0)
elat = models.FloatField(default=0.0)
radec_error = models.FloatField(default=0.0)
class Meta:
ordering = ["-ra"]
def __str__(self):
return "{}".format(self.name)
def get_absolute_url(self):
return "/artsurvey/%i/metasource" % (self.pk)
def get_delete_url(self):
return "/artsurvey/%i/metasource/delete" % (self.pk)
def get_delete_paper_url(self):
return "/artsurvey/%i/metasource/delete/paper" % (self.pk)
def get_delete_upload_url(self):
return "/artsurvey/{}/metasource/upload/delete".format(self.id)
def get_edit_upload_url(self):
return "/artsurvey/{}/metasource/upload/edit".format(self.id)
def get_upload_url(self):
return "/artsurvey/%i/metasource/upload" % (self.pk)
def get_comments(self):
body = []
comments = self.comments.all()
for comment in comments:
body.append("{}: {}".format(comment.owner, comment.body))
return body
class MetaComment(models.Model):
metasource = models.ForeignKey(MetaSource,on_delete=models.CASCADE,related_name='comments')
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
class Meta:
ordering = ['created']
def __str__(self):
return '[{}] {}: {}'.format(self.owner, self.metasource.name, self.body)
def get_delete_url(self):
return "/artsurvey/{}/comment/delete".format(self.id)
class ArtSurvey(models.Model):
""" ArtSurvey makes high-level description of ART-XC catalogue. """
version = models.FloatField(default=0.0, unique=False)
active = models.BooleanField(default=False)
hidden = models.BooleanField(default=False)
archived = models.BooleanField(default=False)
inwork = models.BooleanField(default=False)
label = models.CharField(max_length=12,blank=True, default='')
name = models.CharField(max_length=12,blank=True, default='')
parent = models.ForeignKey('self',blank=True, null=True ,related_name='children', on_delete=models.CASCADE)
notes = models.TextField("notes",max_length=3000, null=True, blank=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["version"]
def get_notes_url(self):
return "/artsurvey/%i/notes/survey" % (self.pk)
def get_absolute_url(self):
return "/artsurvey/catalog"
def set_primary_upload_url(self):
return "/artsurvey/%i/survey/upload/primary" % (self.pk)
def clean_primary_upload_url(self):
return "/artsurvey/%i/survey/upload/primary/clean" % (self.pk)
def get_upload_url(self):
return "/artsurvey/%i/survey/upload" % (self.pk)
def get_delete_upload_url(self):
return "/artsurvey/{}/survey/upload/delete".format(self.pk)
def get_edit_upload_url(self):
return "/artsurvey/{}/survey/upload/edit".format(self.pk)
def __str__(self):
if self.name == '':
name = "{:.1f}".format(self.version)
else:
name = "{}v{:.2f}".format(self.name,self.version)
return "{}S{}{}{}{}{}{}".format(self.label,name,
'R' if self.parent else '',
'H' if self.hidden else '',
'*' if self.active else '',
'A' if self.archived else '',
'W' if self.inwork else '')
class EnergyBand(models.Model):
""" ArtSurvey energy band """
e1 = models.FloatField(default=0.0)
e2 = models.FloatField(default=0.0)
slug = models.SlugField()
def __str__(self):
return "{:.1f}-{:.1f} keV".format(self.e1,self.e2)
class ArtSurveySourceManager(models.Manager):
def create_source(self, src, survey, band):
if (src.skymap):
field = src.skymap.SMAPNR
else:
field=0
log10 = -100.0
if(src.nfalse):
if(src.nfalse > 0.0):
log10 = math.log10(src.nfalse)
ml_log10 = -100.0
if(src.ml_nfalse):
if(src.ml_nfalse > 0.0):
ml_log10 = math.log10(src.ml_nfalse)
crd = SkyCoord(src.ra, src.dec, frame="fk5", unit="deg")
src.ecl_l=crd.transform_to(BarycentricTrueEcliptic).lon.value
src.ecl_b=crd.transform_to(BarycentricTrueEcliptic).lat.value
src.save() # may be not neccesary
# set MSFC flag
marshall = True if(src.ecl_b > 82) else False
source = self.create(band=band, survey=survey,
ra=src.ra, dec=src.dec,
#ra=src.ml_ra, dec=src.ml_dec,
healpix=src.healpix,
healpix_plate=src.healpix_plate,
lii=src.lii, bii=src.bii,
ecl_l=src.ecl_l, ecl_b=src.ecl_b,
#radec_error = src.radec_error,
radec_error = src.ml_radec_err_98,
marshall = marshall,
name = src.name,
name_orig = src.name_orig,
field = field,
SMAPNR = field,
cnts = src.cnts,
cnts_err = src.cnts_err,
cnts_bg = src.cnts_bg,
exptime = src.exptime,
rate = src.rate,
rate_err = src.rate_err,
flux = src.flux,
#flux = src.ml_flux,
flux_err = src.flux_err,
#flux_err = src.ml_flux_err,
fluxerr_up = src.fluxerr_up,
fluxerr_lo = src.fluxerr_lo,
flux_uplim = src.flux_uplim,
cnts0 = src.cnts0,
cnts_er0 = src.cnts_er0,
cnts_bg0 = src.cnts_bg0,
cnts_t0 = src.cnts_t0,
exptime0 = src.exptime0,
flux0 = src.flux0,
flux_er0 = src.flux_er0,
cnts1 = src.cnts1,
cnts_er1 = src.cnts_er1,
cnts_bg1 = src.cnts_bg1,
cnts_t1 = src.cnts_t1,
exptime1 = src.exptime1,
flux1 = src.flux1,
flux_er1 = src.flux_er1,
cnts2 = src.cnts2,
cnts_er2 = src.cnts_er2,
cnts_bg2 = src.cnts_bg2,
cnts_t2 = src.cnts_t2,
exptime2 = src.exptime2,
flux2 = src.flux2,
flux_er2 = src.flux_er2,
cnts3 = src.cnts3,
cnts_er3 = src.cnts_er3,
cnts_bg3 = src.cnts_bg3,
cnts_t3 = src.cnts_t3,
exptime3 = src.exptime3,
flux3 = src.flux3,
flux_er3 = src.flux_er3,
cnts4 = src.cnts4,
cnts_er4 = src.cnts_er4,
cnts_bg4 = src.cnts_bg4,
cnts_t4 = src.cnts_t4,
exptime4 = src.exptime4,
flux4 = src.flux4,
flux_er4 = src.flux_er4,
ext = src.ext,
ext_id = src.ext_id,
sig = src.sig,
#sig = src.ml_sig,
nfalse = src.nfalse,
#nfalse = src.ml_nfalse,
detlike = src.detlike,
#detlike = src.ml_detlike,
log_nfalse=log10,
#log_nfalse=ml_log10,
log_ml_nfalse = ml_log10,
ml_sig = src.ml_sig,
ml_detlike = src.ml_detlike,
ml_nfalse = src.ml_nfalse,
ml_ra = src.ml_ra,
ml_dec = src.ml_dec,
ml_radec_err_90 = src.ml_radec_err_90,
ml_radec_err_98 = src.ml_radec_err_98,
ml_flux = src.ml_flux,
ml_flux_err = src.ml_flux_err,
ml_exp = src.ml_exp)
src.artsurvey_source=source
src.save()
return source
class ArtSurveySource(models.Model):
#catalog_version = models.PositiveIntegerField(default=0)
catalog = models.ManyToManyField(Catalog)
SMAPNR = models.PositiveIntegerField(db_index=True, default=0)
parent = models.ForeignKey('self',blank=True, null=True ,related_name='children', on_delete=models.SET_NULL)
category = models.ForeignKey(Category, null=True, blank=True, on_delete=models.SET_NULL)
survey = models.ForeignKey(ArtSurvey, null=True, on_delete=models.CASCADE)
metasource = models.ForeignKey(MetaSource, null=True, blank=True, on_delete=models.SET_NULL)
metasource_sep = models.FloatField(default=0.0)
metasource_primary = models.ForeignKey(MetaSource, null=True, blank=True, on_delete=models.SET_NULL,related_name="artsurveysource_primary")
band = models.ForeignKey(EnergyBand, null=True, blank=True, on_delete=models.SET_NULL)
gaia3 = models.ManyToManyField(GAIADR3)
gaia3_primary = models.ForeignKey(GAIADR3, null=True, blank=True, related_name='artsurveysource_primary', on_delete=models.SET_NULL)
owner = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
notes = models.TextField("notes",max_length=2000, null=True, blank=True)
notes_paper = models.TextField("notes paper",max_length=5000, null=True, blank=True)
bibtex_paper = models.TextField("bibtex paper",max_length=5000, null=True, blank=True)
#notes_public = models.BooleanField(default=True)
follow_up = models.TextField("follow-up",max_length=5000, null=True, blank=True)
ads = models.ManyToManyField(Ads)
ads_hidden = models.ManyToManyField(Ads, related_name="artsurveysource_hidden")
refid = models.BigIntegerField(default=0)
heasarc = models.ManyToManyField(HeasarcBase)
heasarc_linked = models.ManyToManyField(HeasarcBase, related_name='artsurveysource_linked')
bj2021 = models.ManyToManyField(BJfromVizieR)
bj2021_primary = models.ForeignKey(BJfromVizieR, null=True, blank=True, related_name='artsurveysource_primary', on_delete=models.SET_NULL)
gaiadr3 = models.ManyToManyField(GAIADR3fromVizieR)
gaiadr3_primary = models.ForeignKey(GAIADR3fromVizieR, null=True, blank=True, related_name='artsurveysource_primary', on_delete=models.SET_NULL)
vlass = models.ManyToManyField(VLASSfromVizieR)
vlass_primary = models.ForeignKey(VLASSfromVizieR, null=True, blank=True, related_name='artsurveysource_primary', on_delete=models.SET_NULL)
nvss = models.ManyToManyField(NVSS)
nvss_primary = models.ForeignKey(NVSS, null=True, blank=True, related_name='artsurveysource_primary', on_delete=models.SET_NULL)
first = models.ManyToManyField(FIRST)
first_primary = models.ForeignKey(FIRST, null=True, blank=True, related_name='artsurveysource_primary', on_delete=models.SET_NULL)
sumss = models.ManyToManyField(SUMSS)
sumss_primary = models.ForeignKey(SUMSS, null=True, blank=True, related_name='artsurveysource_primary', on_delete=models.SET_NULL)
allwise = models.ManyToManyField(AllWise)
allwise_primary = models.ForeignKey(AllWise, null=True, blank=True, related_name='artsurveysource_primary', on_delete=models.SET_NULL)
simbad = models.ManyToManyField(Simbad)
simbad_failed = models.BooleanField(default=False, null=True)
xrays = models.BooleanField(default=False, null=True)
""" Simbad failed to respond """
simbad_notfound = models.BooleanField(default=False, null=True)
""" No astronomical object found """
erosita_data = models.BooleanField(default=False, null=True)
""" False if not found in ART-XC/eRosita match table """
#wise_primary = models.ForeignKey(WiseCounterpart, null=True, blank=True, on_delete=models.SET_NULL)
wise_data = models.BooleanField(default=False, null=True)
marshall = models.BooleanField(default=False, null=True)
turkish = models.BooleanField(default=False, null=True)
turkish_date = models.DateTimeField(null=True)
turkpossible = models.BooleanField(default=False, null=True)
"""
sources suitable for TUBITAK (exclude Swift/BAT 105m (2018),
INTEGRAL Reference Catalog (last updated on 16 June 2019) and RXTE
"""
healpix = models.BigIntegerField(db_index=True, default=0)
healpix_plate = models.IntegerField(db_index=True, default=0)
field = models.IntegerField(default=0)
field_ind = models.IntegerField(default=0)
ra = models.FloatField(default=0.0)
""" Right Ascension of the Source """
dec = models.FloatField(default=0.0)
""" Declination of the Source """
lii = models.FloatField(default=0.0)
""" Galactic Longitude """
bii = models.FloatField(default=0.0)
""" Galactic Latitude """
ecl_l = models.FloatField(default=0.0)
ecl_b = models.FloatField(default=0.0)
radec_error = models.FloatField(default=0.0)
""" Positional Uncertainty (arcsec)
Must be exactly radec_error to be consistent with EroTransSource and EroSurveySource
"""
name = models.CharField(max_length=36,blank=True, default='')
name_orig = models.CharField(max_length=22, null=True)
cname = models.CharField(max_length=36,blank=True, null=True,default='')
class_id = models.IntegerField(default=0)
""" Browse Object Classification """
object_class = models.ForeignKey(HeasarcSimpleClass, on_delete=models.SET_NULL, null=True)
""" Related object in HeasarcObjectClass """
class_tentative = models.BooleanField(default=False, null=True)
cnts = models.FloatField(default=0.0,null=True)
cnts_err = models.FloatField(default=0.0,null=True)
cnts_bg = models.FloatField(default=0.0,null=True)
exptime = models.FloatField(default=0.0,null=True)
rate = models.FloatField(default=0.0,null=True)
rate_err = models.FloatField(default=0.0,null=True)
flux = models.FloatField(default=0.0,null=True)
flux_err = models.FloatField(default=0.0,null=True)
fluxerr_lo = models.FloatField(default=0.0,null=True)
fluxerr_up = models.FloatField(default=0.0,null=True)
flux_uplim = models.FloatField(default=0.0,null=True)
cnts0 = models.FloatField(default=0.0,null=True)
cnts_er0 = models.FloatField(default=0.0,null=True)
cnts_bg0 = models.FloatField(default=0.0,null=True)
cnts_t0 = models.FloatField(default=0.0,null=True)
exptime0 = models.FloatField(default=0.0,null=True)
flux0 = models.FloatField(default=0.0,null=True)
flux_er0 = models.FloatField(default=0.0,null=True)
cnts1 = models.FloatField(default=0.0,null=True)
cnts_er1 = models.FloatField(default=0.0,null=True)
cnts_bg1 = models.FloatField(default=0.0,null=True)
cnts_t1 = models.FloatField(default=0.0,null=True)
exptime1 = models.FloatField(default=0.0,null=True)
flux1 = models.FloatField(default=0.0,null=True)
flux_er1 = models.FloatField(default=0.0,null=True)
cnts2 = models.FloatField(default=0.0,null=True)
cnts_er2 = models.FloatField(default=0.0,null=True)
cnts_bg2 = models.FloatField(default=0.0,null=True)
cnts_t2 = models.FloatField(default=0.0,null=True)
exptime2 = models.FloatField(default=0.0,null=True)
flux2 = models.FloatField(default=0.0,null=True)
flux_er2 = models.FloatField(default=0.0,null=True)
cnts3 = models.FloatField(default=0.0,null=True)
cnts_er3 = models.FloatField(default=0.0,null=True)
cnts_bg3 = models.FloatField(default=0.0,null=True)
cnts_t3 = models.FloatField(default=0.0,null=True)
exptime3 = models.FloatField(default=0.0,null=True)
flux3 = models.FloatField(default=0.0,null=True)
flux_er3 = models.FloatField(default=0.0,null=True)
cnts4 = models.FloatField(default=0.0,null=True)
cnts_er4 = models.FloatField(default=0.0,null=True)
cnts_bg4 = models.FloatField(default=0.0,null=True)
cnts_t4 = models.FloatField(default=0.0,null=True)
exptime4 = models.FloatField(default=0.0,null=True)
flux4 = models.FloatField(default=0.0,null=True)
flux_er4 = models.FloatField(default=0.0,null=True)
#ext = models.FloatField(default=0.0)
ext = models.IntegerField(default=0,null=True)
ext_id = models.CharField(max_length=100,blank=True, default='',null=True)
sig = models.FloatField(default=0.0,null=True)
detlike = models.FloatField(default=0.0,null=True)
nfalse = models.FloatField(default=0.0,null=True)
log_nfalse = models.FloatField(default=0.0,null=True)
redshift = models.FloatField(default=0.0, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
""" Date and time of creation. Fully automatic. """
ml_sig = models.FloatField(default=0.0,null=True)
ml_detlike = models.FloatField(default=0.0,null=True)
ml_nfalse = models.FloatField(default=0.0,null=True)
log_ml_nfalse = models.FloatField(default=0.0,null=True)
ml_ra = models.FloatField(default=0.0,null=True)
ml_dec = models.FloatField(default=0.0,null=True)
ml_radec_err_90 = models.FloatField(default=0.0,null=True)
ml_radec_err_98 = models.FloatField(default=0.0,null=True)
ml_flux = models.FloatField(default=0.0,null=True)
ml_flux_err = models.FloatField(default=0.0,null=True)
ml_exp = models.FloatField(default=0.0,null=True)
objects = ArtSurveySourceManager()
class Meta:
get_latest_by = 'created'
def save(self, *args, **kwargs):
#print("Save model ArtSurveySource")
#sys.stdout.write(".")
if(self.survey.archived):
message="<a href='{}'>{}</a> <b>is archived</b>".format(self.get_absolute_url(),
self)
raise PermissionDenied(message)
super(ArtSurveySource, self).save(*args, **kwargs)
def __str__(self):
return "{} {} {}".format(self.name,self.survey,self.band.slug)
def load_skyview_image(self):
return "/artsurvey/{}/load/skyview".format(self.pk)
def load_ps1_color_image(self):
return "/artsurvey/{}/load/ps1/color".format(self.pk)
def load_ps1_gray_image(self):
return "/artsurvey/{}/load/ps1/gray".format(self.pk)
def load_ps1_fits_image(self):
return "/artsurvey/{}/load/ps1/fits".format(self.pk)
def get_r98(self):
return sqrt(self.ml_radec_err_98**2 + 10**2)
def get_galplane_image_path(self):
"""
subpath = self.survey.name[-3:]
if not subpath:
return None
return "/srg/a1/work/rodion/SRG/art-xc/data/galmap/field_data/{}".format(subpath)
"""
path = "/srg/a1/work/rodion/SRG/art-xc/data/galmap/field_data"
crd = SkyCoord(self.ra, self.dec, frame="fk5", unit="deg")
lon = crd.galactic.l.value
lat = crd.galactic.b.value
glon = int(5.0*round(lon/5.0))
if(glon == 360):
glon = 0
glat = int(5.0*round(lat/5.0))
subpath="{:03d}+0".format(glon)
dirpath="{}/{}".format(path,subpath)
if(osp.exists("{}/{}".format(dirpath,"img_flux_0.fits.fz")) and abs(lat) < 2.5):
return dirpath
else:
return None
def get_SMAPNR(self):
return "{:06d}".format(self.SMAPNR)
def get_galplane_image_url(self):
"""
subpath = self.survey.name[-3:]
if not subpath:
return None
dirpath="{}/{}".format(path,subpath)
if(osp.exists(dirpath)):
return "/galplane/{}".format(subpath)
else:
pass
"""
path = "/srg/a1/work/rodion/SRG/art-xc/data/galmap/field_data"
crd = SkyCoord(self.ra, self.dec, frame="fk5", unit="deg")
lon = crd.galactic.l.value
lat = crd.galactic.b.value
# map to 5degx5deg tiles
glon = int(5.0*round(lon/5.0))
print(glon)
if(glon == 360):
glon = 0
glat = int(5.0*round(lat/5.0))
subpath="{:03d}".format(glon)
dirpath="{}/{}/12g".format(path,subpath)
if(osp.exists("{}/{}".format(dirpath,"img_flux_0.fits.fz")) and abs(lat) < 5.0):
return "/galplane/{}".format(subpath)
else:
return None
def get_survey_primary_image_url(self):
upload = self.survey.uploads.all().filter(primary=True).first()
if upload:
return upload.get_download_url()
else:
return None
def get_absolute_url(self):
return "/artsurvey/%i/artsource" % (self.pk)
def get_transfer_url(self):
return "/artsurvey/%i/transfer" % (self.pk)
def get_add_to_selection_url(self):
return "/artsurvey/%i/selection/add" % (self.pk)
def get_remove_from_selection_url(self):
return "/artsurvey/%i/selection/remove" % (self.pk)
def get_remove_from_selection_profile_url(self):
return "/artsurvey/%i/selection/remove/profile" % (self.pk)
def get_remove_from_basket_url(self):
return "/artsurvey/%i/selection/remove/basket" % (self.pk)
def new_heasarc_source(self):
return "/artsurvey/%i/usercat" % (self.pk)
def get_ds9_region(self):
return "/artsurvey/%i/artsource/ds9" % (self.pk)
def get_ds9_region_linked(self):
return "/artsurvey/%i/artsource/ds9/linked" % (self.pk)
def get_markbad_url(self):
return "/artsurvey/%i/markbad" % (self.pk)
def get_delete_url(self):
return "/artsurvey/%i/delete" % (self.pk)
def get_base_url(self):
return "/artsurvey/%i/" % (self.pk)
def get_clean_wise_url(self):
return "/artsurvey/%i/wise/clean/" % (self.pk)
def get_clean_allwise_url(self):
return "/artsurvey/%i/allwise/clean/" % (self.pk)
def get_clean_nvss_url(self):
return "/artsurvey/%i/nvss/clean/" % (self.pk)
def get_clean_vlass_url(self):
return "/artsurvey/%i/nvss/clean/" % (self.pk)
def get_clean_first_url(self):
return "/artsurvey/%i/first/clean/" % (self.pk)
def get_clean_sumss_url(self):
return "/artsurvey/%i/sumss/clean/" % (self.pk)
def get_clean_gaiadr3_url(self):
return "/artsurvey/%i/gaiadr3/clean/" % (self.pk)
def get_clean_bj2021_url(self):
return "/artsurvey/%i/bj2021/clean/" % (self.pk)
def get_vizier_url(self):
return "/artsurvey/%i/vizier" % (self.pk)
def get_type_url(self):
return "/artsurvey/%i/type" % (self.pk)
def get_notes_url(self):
return "/artsurvey/%i/notes" % (self.pk)
def get_cname_url(self):
return "/artsurvey/%i/cname" % (self.pk)
def get_update_category_url(self):
return "/artsurvey/category/{}/update".format(self.pk)
def get_skymap_url(self):
return "/srgcat/{}/field_radec/{}/{}".format(self.field,self.ra,self.dec)
def get_mark_tentative_url(self):
return "/artsurvey/tentative/{}/mark".format(self.pk)
def get_remove_tentative_url(self):
return "/artsurvey/tentative/{}/remove".format(self.pk)
def get_mark_newxray_url(self):
return "/artsurvey/newxray/{}/mark".format(self.pk)
def get_remove_newxray_url(self):
return "/artsurvey/newxray/{}/remove".format(self.pk)
def get_mark_turkish_url(self):
return "/artsurvey/turkish/{}/mark".format(self.pk)
def get_remove_turkish_url(self):
return "/artsurvey/turkish/{}/remove".format(self.pk)
def get_clean_class_url(self):
return "/artsurvey/type/{}/clean".format(self.pk)
#def get_make_notes_public_url(self):
# return "/artsurvey/notes_public/{}/make".format(self.pk)
#def get_remove_notes_public_url(self):
# return "/artsurvey/notes_public/{}/remove".format(self.pk)
def get_add_bibcode_url(self):
return "/nasa/%i/bibcode" % (self.pk)
def get_add_counterpart_url(self):
return "/artsurvey/%i/counterpart" % (self.pk)
def get_delete_bibcode_url(self):
return "/nasa/%i/bibcode/delete" % (self.pk)
def get_update_bibcode_url(self):
return "/nasa/%i/bibcode/update" % (self.pk)
def get_hide_bibcode_url(self):
return "/nasa/%i/bibcode/hide" % (self.pk)
def get_unhide_bibcode_url(self):
return "/nasa/%i/bibcode/unhide" % (self.pk)
def get_metasource_group_url(self):
return "/artsurvey/%i/metasource/group" % (self.pk)
def get_add_other_name_url(self):
return "/artsurvey/%i/oname" % (self.pk)
def get_update_other_name_url(self):
return "/artsurvey/%i/oname/update" % (self.pk)
def get_update_source_url(self):
return "/artsurvey/%i/update/source" % (self.pk)
def get_swiftbat_count(self):
swiftbat = HeasarcBase.objects.instance_of(HeasarcSwiftBAT105m).filter(healpix=self.healpix)
return swiftbat.count()
def get_4xmm_count(self):
return HeasarcBase.objects.instance_of(Heasarc4XMMDR9).filter(healpix=self.healpix).count()
def get_rosat_count(self):
return HeasarcBase.objects.instance_of(HeasarcRASS2RXS).filter(healpix=self.healpix).count()
def get_integral_count(self):
return HeasarcBase.objects.instance_of(HeasarcIntRefCat).filter(healpix=self.healpix).count()
def get_upload_url(self):
return "/artsurvey/%i/upload" % (self.pk)
def get_delete_upload_url(self):
return "/artsurvey/{}/upload/delete".format(self.id)
def get_edit_upload_url(self):
return "/artsurvey/{}/upload/edit".format(self.id)
@property
def get_category(self):
return self.category
def get_log10_nfalse(self):
"""
log10 = -100.0
if(self.nfalse > 0.0):
log10 = math.log10(self.nfalse)
return log10
"""
return self.log_nfalse
def get_detlike100(self):
if(self.detlike < 100):
return "{:.2f}".format(self.detlike)
else:
return "> 100"
def get_erosita_ratio(self):
ratio=-1.0
if(hasattr(self, 'erositamatch')):
ratio = float(self.flux/self.erositamatch.flux)
return ratio
def get_radio_total(self):
return self.nvss.all().count() + self.first.all().count() + self.sumss.all().count() + self.vlass.all().count()
def get_link_heasarc_url(self):
return "/artsurvey/%i/link/heasarc/" % (self.pk)
def get_unlink_heasarc_url(self):
return "/artsurvey/%i/unlink/heasarc/" % (self.pk)
def get_unlink_heasarc_all_url(self):
return "/artsurvey/%i/unlink/heasarc/all" % (self.pk)
def get_otype(self):
if(self.object_class):
otype=self.object_class.class_name
else:
return ''
s='CV'
if(otype.startswith(s)):
otype=s
s='STAR'
if(otype.startswith(s)):
otype=s
s='LMXB'
if(otype.startswith(s)):
otype=s
s='HMXB'
if(otype.startswith(s)):
otype=s
s='AGN'
if(otype.startswith(s)):
otype=s
s='SEYFERT'
if(otype.startswith(s)):
otype='SEYFERT'
if(otype.startswith('LINER')):
otype='SEYFERT'
s='UNIDENTIFIED'
if(otype.startswith(s)):
otype='UNIDENT'
if(self.class_tentative):
otype+='?'
return otype
def if_linked_to(self, heasarc):
return True if heasarc in self.heasarc_linked.all() else False
def get_heasarc_linked_all(self):
return True if self.heasarc_linked.all().count() else False
def get_heasarc_linked_optics(self):
lst = []
linked = self.heasarc_linked.all()
for h in linked:
if(h.gaia3_primary):
lst.append({'ra':h.gaia3_primary.ra,'dec':h.gaia3_primary.dec,'name':h.gaia3_primary.name,'color':'#00FF00'})
else:
for s in h.gaia3.all():
lst.append({'ra':s.ra,'dec':s.dec,'name':'Gaia3','color':''})
if(h.allwise_primary):
lst.append({'ra':h.allwise_primary.ra,'dec':h.allwise_primary.dec,'name':h.allwise_primary.name,'color':'#00FF00'})
else:
for s in h.allwise.all():
lst.append({'ra':s.ra,'dec':s.dec,'name':'AllWise','color':'green'})
if(h.glimpse_primary):
lst.append({'ra':h.glimpse_primary.ra,'dec':h.glimpse_primary.dec,'name':h.glimpse_primary.name,'color':'#00FF00'})
else:
for s in h.glimpse.all():
lst.append({'ra':s.ra,'dec':s.dec,'name':'GLIMPSE','color':'green'})
if(h.vlass_primary):
lst.append({'ra':h.vlass_primary.ra,'dec':h.vlass_primary.dec,'name':h.vlass_primary.name,'color':'#00FF00'})
else:
for s in h.vlass.all():
lst.append({'ra':s.ra,'dec':s.dec,'name':'VLASS','color':'green'})
if(h.twomass_primary):
lst.append({'ra':h.twomass_primary.ra,'dec':h.twomass_primary.dec,'name':h.twomass_primary.name,'color':'#00FF00'})
else:
for s in h.twomass.all():
lst.append({'ra':s.ra,'dec':s.dec,'name':'2MASS','color':'green'})
for s in h.usercat.all():
lst.append({'ra':s.ra,'dec':s.dec,'name':'UserCat','color':'#00FF00'})
return lst
def get_otype(self):
if(self.object_class):
otype=self.object_class.class_name
else:
return ''
s='CV'
if(otype.startswith(s)):
otype=s
s='STAR'
if(otype.startswith(s)):
otype=s
s='LMXB'
if(otype.startswith(s)):
otype=s
s='HMXB'
if(otype.startswith(s)):
otype=s
s='AGN'
if(otype.startswith(s)):
otype=s
s='SEYFERT'
if(otype.startswith(s)):
otype='SEYFERT'
if(otype.startswith('LINER')):
otype='SEYFERT'
s='UNIDENT'
if(otype.startswith(s)):
otype='UNIDENT'
if(self.class_tentative):
otype+='?'
return otype
def get_flux_str_m11power(self):
koeff=1e-12
#return "{:.2f} $\pm$ {}".format(self.flux/koeff,self.flux_err)
if(self.fluxerr_lo > 0.0 and self.fluxerr_up > 0.0):
pass
else:
return "{:.2f}".format(self.flux/koeff)
er1 = int((self.fluxerr_lo/koeff)*100)
er2 = int((self.fluxerr_up/koeff)*100)
if(er1 == er2):
return "{:.2f} $\pm$ {:.2f}".format(self.flux/koeff,self.fluxerr_lo/koeff)
else:
return "{:.2f} $_{{ -{:.2f} }}^{{ +{:.2f} }}$ ".format(self.flux/koeff,self.fluxerr_lo/koeff,self.fluxerr_up/koeff)
def get_cname_ads_url(self):
return "https://ui.adsabs.harvard.edu/search/q=object%3A%22{}%22&sort=date%20desc%2C%20bibcode%20desc&p_=0".format(urllib.parse.quote_plus(self.cname))
class OpticalCounterpart(models.Model):
source = models.ForeignKey(ArtSurveySource, on_delete=models.CASCADE)
name = models.CharField(max_length=60,default='')
objid = models.BigIntegerField(default=0)
t_objid = models.CharField(max_length=15,default='')
redshift = models.FloatField(default=0,validators=[MinValueValidator(0.0)])
mag = models.FloatField(default=0,validators=[MinValueValidator(0.0)], null=True, blank=True)
ra = models.FloatField(default=0.0)
dec = models.FloatField(default=0.0)
def __str__(self):
return self.source.name
class OtherName(models.Model):
source = models.ForeignKey(ArtSurveySource, on_delete=models.CASCADE)
name = models.CharField(max_length=60,default='')
owner = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
def __str__(self):
return "{}".format(self.name)
def get_update_url(self):
return "/artsurvey/%i/oname/update" % (self.pk)
def get_delete_url(self):
return "/artsurvey/%i/oname/delete" % (self.pk)
class WiseCounterpart(models.Model):
source = models.ForeignKey(ArtSurveySource, on_delete=models.CASCADE)
sep = models.FloatField(default=0,validators=[MinValueValidator(0.0)])
objID = models.BigIntegerField(default=0)
raStack = models.FloatField(default=0.0)
decStack = models.FloatField(default=0.0)
raStackErr = models.FloatField(default=0.0)
decStackErr = models.FloatField(default=0.0)
raMean = models.FloatField(default=0.0)
decMean = models.FloatField(default=0.0)
raMeanErr = models.FloatField(default=0.0)
decMeanErr = models.FloatField(default=0.0)
objInfoFlag = models.BigIntegerField(default=0)
qualityFlag = models.IntegerField(default=0)
primaryDetection = models.BooleanField(default=False, null=True)
bestDetection = models.BooleanField(default=False, null=True) #models.IntegerField(default=0)
gPSFMag = models.FloatField(default=0.0, null=True)
gPSFMagErr = models.FloatField(default=0.0)
gApMag = models.FloatField(default=0.0)
gApMagErr= models.FloatField(default=0.0)
gKronMag= models.FloatField(default=0.0)
gKronMagErr= models.FloatField(default=0.0)
rPSFMag= models.FloatField(default=0.0, null=True)
rPSFMagErr= models.FloatField(default=0.0)
rApMag= models.FloatField(default=0.0)
rApMagErr= models.FloatField(default=0.0)
rKronMag= models.FloatField(default=0.0)
rKronMagErr= models.FloatField(default=0.0)
iPSFMag= models.FloatField(default=0.0, null=True)
iPSFMagErr= models.FloatField(default=0.0)
iApMag= models.FloatField(default=0.0)
iApMagErr= models.FloatField(default=0.0)
iKronMag= models.FloatField(default=0.0)
iKronMagErr= models.FloatField(default=0.0)
zPSFMag= models.FloatField(default=0.0, null=True)
zPSFMagErr= models.FloatField(default=0.0)
zApMag= models.FloatField(default=0.0)
zApMagErr= models.FloatField(default=0.0)
zKronMag= models.FloatField(default=0.0)
zKronMagErr= models.FloatField(default=0.0)
yPSFMag= models.FloatField(default=0.0, null=True)
yPSFMagErr= models.FloatField(default=0.0)
yApMag= models.FloatField(default=0.0)
yApMagErr= models.FloatField(default=0.0)
yKronMag= models.FloatField(default=0.0)
yKronMagErr= models.FloatField(default=0.0)
wisefield= models.CharField(max_length=8, default='')
fitext = models.BooleanField(default=False, null=True)
devaucou = models.BooleanField(default=False, null=True)
star = models.BooleanField(default=False, null=True)
w1flux= models.FloatField(default=0.0, null=True)
dw1flux= models.FloatField(default=0.0, null=True)
w1mag= models.FloatField(default=0.0, null=True)
dw1mag= models.FloatField(default=0.0, null=True)
w1reff= models.FloatField(default=0.0, null=True)
w2flux= models.FloatField(default=0.0, null=True)
dw2flux= models.FloatField(default=0.0, null=True)
w2mag= models.FloatField(default=0.0, null=True)
dw2mag= models.FloatField(default=0.0, null=True)
w2reff= models.FloatField(default=0.0, null=True)
primary = models.BooleanField(default=False, null=True)
def __str__(self):
return self.source.name
def w1w2(self):
if self.w1mag and self.w2mag:
return self.w1mag-self.w2mag
else:
return None
def w1w2_error(self):
if self.dw1mag and self.dw2mag:
return sqrt(self.dw1mag*self.dw1mag + self.dw2mag*self.dw2mag)
else:
return None
def get_irsa_url(self):
return "http://irsa.ipac.caltech.edu/applications/wise/#id=Hydra_wise_wise_1&DoSearch=true&schema=allwise-multiband&intersect=CENTER&subsize=0.20&mcenter=mcen&band=1,2,3,4&dpLevel=3a&UserTargetWorldPt={};{};EQ_J2000&SimpleTargetPanel.field.resolvedBy=simbadthenned&coaddId=&projectId=wise&searchName=wise_1&startIdx=0&pageSize=0&shortDesc=Position&isBookmarkAble=true&isDrillDownRoot=true&isSearchResult=true".format(self.raStack,self.decStack)
class eRositaMatch(models.Model):
source = models.OneToOneField(ArtSurveySource, on_delete=models.CASCADE)
ero_exp = models.FloatField(default=0.0)
lkh = models.FloatField(default=0.0)
sep_soft = models.FloatField(default=0.0, null=True)
match_soft = models.BooleanField(default=False, null=True) #models.CharField(max_length=5, blank=True, null=True, default='')
srcname_soft = models.CharField(max_length=21, blank=True, null=True, default='')
hpidx_soft = models.BigIntegerField(default=0, null=True)
RA_fin_soft = models.FloatField(default=0.0, null=True)
DEC_fin_soft = models.FloatField(default=0.0, null=True)
RA_soft = models.FloatField(default=0.0, null=True)
DEC_soft = models.FloatField(default=0.0, null=True)
RADEC_ERR_soft = models.FloatField(default=0.0, null=True)
DET_LIKE_0_soft = models.FloatField(default=0.0, null=True)
ML_FLUX_0_soft = models.FloatField(default=0.0, null=True)
ML_FLUX_ERR_0_soft = models.FloatField(default=0.0, null=True)
ML_CTS_0_soft = models.FloatField(default=0.0, null=True)
ML_CTS_ERR_0_soft = models.FloatField(default=0.0, null=True)
ML_BKG_0_soft = models.FloatField(default=0.0, null=True)
EXT_soft = models.FloatField(default=0.0, null=True)
EXT_LIKE_soft = models.FloatField(default=0.0, null=True)
EXT_ERR_soft = models.FloatField(default=0.0, null=True)
ML_EXP_1_soft = models.FloatField(default=0.0, null=True)
sep_med = models.FloatField(default=0.0, null=True)
match_med = models.BooleanField(default=False, null=True) #models.CharField(max_length=5, blank=True, null=True, default='')
srcname_med = models.CharField(max_length=21, blank=True, null=True, default='')
hpidx_med = models.BigIntegerField(default=0, null=True)
RA_fin_med = models.FloatField(default=0.0, null=True)
DEC_fin_med = models.FloatField(default=0.0, null=True)
RA_med = models.FloatField(default=0.0, null=True)
DEC_med = models.FloatField(default=0.0, null=True)
RADEC_ERR_med = models.FloatField(default=0.0, null=True)
DET_LIKE_0_med = models.FloatField(default=0.0, null=True)
ML_FLUX_0_med = models.FloatField(default=0.0, null=True)
ML_FLUX_ERR_0_med = models.FloatField(default=0.0, null=True)
ML_CTS_0_med = models.FloatField(default=0.0, null=True)
ML_CTS_ERR_0_med = models.FloatField(default=0.0, null=True)
ML_BKG_0_med = models.FloatField(default=0.0, null=True)
EXT_med = models.FloatField(default=0.0, null=True)
EXT_LIKE_med = models.FloatField(default=0.0, null=True)
EXT_ERR_med = models.FloatField(default=0.0, null=True)
ML_EXP_1_med = models.FloatField(default=0.0, null=True)
sep_hard = models.FloatField(default=0.0, null=True)
match_hard = models.BooleanField(default=False, null=True) #models.CharField(max_length=5, blank=True, null=True, default='')
srcname_hard = models.CharField(max_length=21, blank=True, null=True, default='')
hpidx_hard = models.BigIntegerField(default=0, null=True)
RA_fin_hard = models.FloatField(default=0.0, null=True)
DEC_fin_hard = models.FloatField(default=0.0, null=True)
RA_hard = models.FloatField(default=0.0, null=True)
DEC_hard = models.FloatField(default=0.0, null=True)
RADEC_ERR_hard = models.FloatField(default=0.0, null=True)
DET_LIKE_0_hard = models.FloatField(default=0.0, null=True)
ML_FLUX_0_hard = models.FloatField(default=0.0, null=True)
ML_FLUX_ERR_0_hard = models.FloatField(default=0.0, null=True)
ML_CTS_0_hard = models.FloatField(default=0.0, null=True)
ML_CTS_ERR_0_hard = models.FloatField(default=0.0, null=True)
ML_BKG_0_hard = models.FloatField(default=0.0, null=True)
EXT_hard = models.FloatField(default=0.0, null=True)
EXT_LIKE_hard = models.FloatField(default=0.0, null=True)
EXT_ERR_hard = models.FloatField(default=0.0, null=True)
ML_EXP_1_hard = models.FloatField(default=0.0, null=True)
sep_simb = models.FloatField(default=0.0, null=True)
match_simb = models.BooleanField(default=False, null=True) # models.CharField(max_length=5, blank=True, null=True, default='')
ra_match = models.FloatField(default=0.0, null=True)
dec_match = models.FloatField(default=0.0, null=True)
RAJ2000_simb = models.FloatField(default=0.0, null=True)
DEJ2000_simb = models.FloatField(default=0.0, null=True)
z_simb = models.FloatField(default=0.0, null=True)
otype_simb = models.CharField(max_length=17, blank=True, null=True, default='')
def get_fields(self):
return [(field.name, field.value_to_string(self)) for field in eRositaMatch._meta.fields]
def __str__(self):
return self.source.name
class ArtSurveyParams(models.Model):
ALLSKY = 'allsky'
RU = 'ru'
DE = 'de'
#RUDE = 'ru,de'
OWNERSHIP = [
(ALLSKY,'All-sky'),
(RU, 'RU-sky'),
(DE, 'DE-sky'),
#(RUDE, 'RU,DE'),
]
E0 = 'E0'
E1 = 'E1'
E2 = 'E2'
E3 = 'E3'
E4 = 'E4'
E5 = 'E5'
ALL = 'ALL'
BANDS = [
(E0,'4-12 keV'),
(E1,'4-7 keV'),
(E2,'7-12 keV'),
(E3,'12-20 keV'),
(E4,'20-30 keV'),
(E5,'3-12 keV'),
(ALL,'All bands'),
]
MSFC_FILT = 'MSFC_FILT'
MSFC_EXCL = 'MSFC_EXCL'
MARSHALL_SELECT = [
("", "None"),
(MSFC_FILT,'NEP filter'),
(MSFC_EXCL,'NEP exclude'),
]
owner = models.OneToOneField(User, related_name="artsurveyparams", on_delete=models.CASCADE)
history = models.TextField(default='', editable=False)
sign_ml_min = models.FloatField(default=None, blank=True, null=True, help_text='ML significance') # help_text='not applied to extended sources (EXT>1)')
sign_ml_max = models.FloatField(default=None, blank=True, null=True, help_text='ML significance') #help_text='not applied to extended sources (EXT>1)')
log_nfalse_min = models.FloatField(default=None, blank=True, null=True, help_text='not applied to extended sources (EXT>1)')
log_nfalse_max = models.FloatField(default=None, blank=True, null=True, help_text='not applied to extended sources (EXT>1)')
log_ml_nfalse_min = models.FloatField(default=-1.0, blank=True, null=True, help_text='not applied to extended sources (EXT>1)')
log_ml_nfalse_max = models.FloatField(default=None, blank=True, null=True, help_text='not applied to extended sources (EXT>1)')
exposure_min = models.FloatField(default=None, blank=True, null=True, help_text='Minimal exposure time')
detlike_min = models.FloatField(default=None, blank=True, null=True, help_text='not applied to extended sources (EXT>1)')
detlike_max = models.FloatField(default=None, blank=True, null=True, help_text='not applied to extended sources (EXT>1)')
ext_min = models.IntegerField(default=None, blank=True, null=True, help_text='Minimal extention in arcseconds')
ext_max = models.IntegerField(default=None, blank=True, null=True, help_text='Maximum extention in arcseconds')
class_startswith = models.CharField(max_length=36, blank=True, null=True, default='')
cname_contains = models.CharField(max_length=36, blank=True, null=True, default='')
survey = models.ForeignKey(ArtSurvey, null=True, blank=True, on_delete=models.SET_NULL, help_text='Survey number <b>N=[1..8]</b> of version <b>V=[0..9]</b> is named as <b>SN.V</b>;</br> The combined survey is labeled as <b>SN<...>N.V</b>;<br>Tags: active (<b>*</b>), in work (<b>W</b>), archived (<b>A</b>)')
exclude_survey = models.ForeignKey(ArtSurvey, related_name="exclude_survey", null=True, blank=True, on_delete=models.SET_NULL)
exclude_log_nfalse = models.FloatField(default=-1.0, blank=True, null=True, help_text='not active, do not use it.')
exclude_log_ml_nfalse = models.FloatField(default=-1.0, blank=True, null=True)
category = models.ForeignKey(Category, null=True, blank=True, on_delete=models.SET_NULL, help_text='Show sources with this Category only')
exclude_category = models.ForeignKey(Category, null=True, blank=True, on_delete=models.SET_NULL, related_name="exclude_category", help_text='Hide sources with this Category')
category_unclassified = models.BooleanField(default=False, help_text='Show sources without any Category')
ecl_lat_min = models.FloatField(default=None, blank=True, null=True, help_text='Ecliptic latitude min')
ecl_lat_max = models.FloatField(default=None, blank=True, null=True, help_text='Ecliptic latitude max')
dec_min = models.FloatField(default=None, blank=True, null=True, help_text='J2000 Declination min')
dec_max = models.FloatField(default=None, blank=True, null=True, help_text='J2000 Declination max')
glat_min = models.FloatField(default=None, blank=True, null=True, help_text='Galactic latitude min')
glat_max = models.FloatField(default=None, blank=True, null=True, help_text='Galactic latitude max')
circle_ra = models.FloatField(default=0.0, blank=True, null=True, help_text='Selection circle RA (not implemented yet)')
circle_dec = models.FloatField(default=0.0, blank=True, null=True, help_text='Selection circle Dec (not implemented yet)')
circle_rmax_deg = models.FloatField(default=0.0, blank=True, null=True, help_text='Selection circle Rmax in degrees (not implemented yet)')
gaia_primary = models.BooleanField(default=False, help_text='Select sources with Gaia counterpart')
allwise_primary = models.BooleanField(default=False, help_text='Select sources with AllWISE counterpart')
turk_possible = models.BooleanField(default=False, help_text='Sources suitable for TUBITAK*')
#marshall_filter = models.BooleanField(default=False, help_text='Show MSFC sources in NEP')
#marshall_exclude = models.BooleanField(default=False, help_text='Exclude MSFC sources in NEP')
sky = models.CharField(
max_length=6,
choices=OWNERSHIP,
default=ALLSKY,
)
band = models.CharField(
max_length=10,
choices=BANDS,
default=E0,
help_text='<b>E0:</b> 4-12 keV, <b>E1:</b> 4-7 keV, <b>E2:</b> 7-12 keV, <b>E3:</b> 12-20 keV, <b>E4:</b> 20-30 keV'
)
exclude_band = models.CharField(
max_length=10,
choices=BANDS,
default=E0,
)
marshall = models.CharField(
max_length=10,
choices=MARSHALL_SELECT,
default=None, null=True,blank=True,
help_text='MSFC sources in NEP'
)
class ArtSurveyMatchParams(models.Model):
E0 = 'E0'
E1 = 'E1'
E2 = 'E2'
E3 = 'E3'
E4 = 'E4'
E5 = 'E5'
BANDS = [
(E0,'4-12 keV'),
(E1,'4-7 keV'),
(E2,'7-12 keV'),
(E3,'12-20 keV'),
(E4,'20-30 keV'),
(E5,'3-15 keV'),
]
owner = models.OneToOneField(User, related_name="artsurveymatchparams", on_delete=models.CASCADE)
survey1 = models.ForeignKey(ArtSurvey, related_name='matchsurvey1', null=True, blank=True, on_delete=models.SET_NULL)
survey2 = models.ForeignKey(ArtSurvey, related_name='matchsurvey2', null=True, blank=True, on_delete=models.SET_NULL)
band1 = models.CharField(max_length=10,choices=BANDS,default=E0,)
band2 = models.CharField(max_length=10,choices=BANDS,default=E0,)
sign_min1 = models.FloatField(default=0.0, blank=True, null=True)
sign_max1 = models.FloatField(default=1000.0, blank=True, null=True)
#detlike_min1 = models.FloatField(default=None, blank=True, null=True)
sign_min2 = models.FloatField(default=0.0, blank=True, null=True)
sign_max2 = models.FloatField(default=1000.0, blank=True, null=True)
#detlike_min2 = models.FloatField(default=None, blank=True, null=True)
log_ml_nfalse_min1 = models.FloatField(default=-1.0, blank=True, null=True, help_text='not applied to extended sources (EXT>1)')
log_ml_nfalse_max1 = models.FloatField(default=None, blank=True, null=True, help_text='not applied to extended sources (EXT>1)')
log_ml_nfalse_min2 = models.FloatField(default=-1.0, blank=True, null=True, help_text='not applied to extended sources (EXT>1)')
log_ml_nfalse_max2 = models.FloatField(default=None, blank=True, null=True, help_text='not applied to extended sources (EXT>1)')
Rmax = models.FloatField(default=40.0, blank=True, null=True)
maxdist = models.FloatField(default=120.0, blank=True, null=True)
f2f1_ratio_min = models.FloatField(default=0.001, blank=True, null=True)
f2f1_ratio_max = models.FloatField(default=1000.0, blank=True, null=True)
class Upload(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, default=None, unique=False, related_name="uploads")
artsources = models.ManyToManyField(ArtSurveySource, blank=True, related_name="uploads")
metasource = models.ForeignKey(MetaSource, null=True, blank=True, on_delete=models.SET_NULL, related_name="uploads")
survey = models.ForeignKey(ArtSurvey, null=True, blank=True, on_delete=models.SET_NULL, related_name="uploads")
title = models.CharField(max_length=128)
notes = models.TextField("notes",max_length=2000, null=True, blank=True)
filename = models.CharField(max_length=256)
filefield = models.FileField(upload_to=upload_filename, storage=FS, validators=[validate_upload])
uploaded = models.DateTimeField(auto_now_add=True)
primary = models.BooleanField(default=False, help_text='Primary')
def get_delete_file_url(self):
return "/artsurvey/upload/%d/delete/file" % (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 self.title
def get_download_url(self):
return "/uploads/artsurvey/{}".format(self.filefield)
def get_absolute_url(self):
return "/artsurvey/upload/{}/show".format(self.id)
@property
def isfits(self):
return self.filename.endswith("fits") or self.filename.endswith("evt") or self.filename.endswith("evt.gz") or self.filename.endswith("fits.gz") or self.filename.endswith("FTZ") or self.filename.endswith("fz")
@property
def isreg(self):
return self.filename.endswith("reg")
@receiver(models.signals.post_delete, sender=Upload)
def auto_delete_file_on_delete(sender, instance, **kwargs):
"""
Deletes file from filesystem
when corresponding `Upload` object is deleted.
"""
print("Upload: trigger post_delete for {}".format(instance))
if instance.filefield:
if os.path.isfile(instance.filefield.path):
os.remove(instance.filefield.path)
class ArtSelection(models.Model):
owner = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
sources = models.ManyToManyField(ArtSurveySource, blank=True)
def __str__(self):
return self.user
class ArtBasket(models.Model):
#owner = models.ForeignKey(User, on_delete=models.CASCADE, default=None, unique=False, verbose_name="ArtBasket", related_name="baskets")
owner = models.ForeignKey(User, on_delete=models.CASCADE)
sources = models.ManyToManyField(ArtSurveySource, blank=True)
title = models.CharField(max_length=128)
notes = models.TextField("Notes",max_length=2000, null=True, blank=True, validators=[MaxLengthValidator(1600)])
#begin = models.DateTimeField(blank=True, null=True, auto_now_add=True)
#end = models.DateTimeField(blank=True, null=True)
#active = models.BooleanField(default=True)
#created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "{}".format(self.title)
def get_absolute_url(self):
return "/artsurvey/basket/{}/show".format(self.id)
def get_update_url(self):
return "/artsurvey/basket/{}/update".format(self.id)
def get_delete_url(self):
return "/artsurvey/basket/{}/delete".format(self.id)
def get_sources_count(self):
return "{}".format(self.sources.all().count())
class ArtBasketForm(forms.ModelForm):
class Meta:
model=ArtBasket
fields=('title','notes',)