Skip to content
Snippets Groups Projects
models.py 46.3 KiB
Newer Older
    class Meta:
        ordering = ['-created', '-N']
        unique_together = ("event","N")

    def __unicode__(self):
        return "%s-%s-%d" % (self.event.graceid(), self.group.name, self.N)

    # A counter for Eels associated with a given event. This is 
    # important for addressibility.
    N = models.IntegerField(null=False)

    # The time at which this Eel was created. Important for event auditing.
    created = models.DateTimeField(auto_now_add=True)

    # The gracedb event that this Eel relates to
    event = models.ForeignKey(Event)

    # The responsible author of this communication
    submitter  = models.ForeignKey(UserModel)  # from a table of people

    # The MOU group responsible 
    group = models.ForeignKey(EMGroup)       # from a table of facilities

    # The instrument used or intended for the imaging implied by this footprint
    instrument = models.CharField(max_length=200, blank=True)

    # Facility-local identifier for this footprint
    footprintID= models.TextField(blank=True)

    # Now the global ID is a concatenation: facilityName#footprintID

    # the EM waveband used for the imaging as below
    waveband   = models.CharField(max_length=25, choices=EMSPECTRUM)

    # The center of the bounding box of the rectangular footprints, right ascension and declination
    # in J2000 in decimal degrees
    ra         = models.FloatField(null=True)
    dec        = models.FloatField(null=True)

    # The width and height (RA range and Dec range) in decimal degrees of each image
    raWidth    = models.FloatField(null=True)
    decWidth   = models.FloatField(null=True)

    # The GPS time of the middle of the bounding box of the imaging time
    gpstime    = models.PositiveIntegerField(null=True)

    # The duration of each image in seconds
    duration   = models.PositiveIntegerField(null=True)

    # The lists of RA and Dec of the centers of the images
    raList         = models.TextField(blank=True)
    decList        = models.TextField(blank=True)

    # The width and height of each individual image
    raWidthList    = models.TextField(blank=True)
    decWidthList   = models.TextField(blank=True)

    # The list of GPS times of the images
    gpstimeList        = models.TextField(blank=True)

    # The duration of each individual image
    durationList   = models.TextField(blank=True)

    # Event Log status
    EEL_STATUS_CHOICES = (('FO','FOOTPRINT'), ('SO','SOURCE'), ('CO','COMMENT'), ('CI','CIRCULAR'))
    eel_status     = models.CharField(max_length=2, choices=EEL_STATUS_CHOICES)

    # Observation status. If OBSERVATION, then there is a good chance of good image
    OBS_STATUS_CHOICES = (('NA', 'NOT APPLICABLE'), ('OB','OBSERVATION'), ('TE','TEST'), ('PR','PREDICTION'))
    obs_status     = models.CharField(max_length=2, choices=OBS_STATUS_CHOICES)

    # This field is natural language for human
    comment = models.TextField(blank=True)
    # This field is formal struct by a syntax TBD
    # for example  {"phot.mag.limit": 22.3}
    extra_info_dict = models.TextField(blank=True)

    # For AutoIncrementModel save
    AUTO_FIELD = 'N'

    # Validates the input and builds  bounding box in RA/Dec/GPS
    def validateMakeRects(self):
        # get all the list based position and times and their widths
        raRealList = []
        rawRealList = []
        # add a [ and ] to convert the input csv list to a json parsable text

        if self.raList:        raRealList = json.loads('['+self.raList+']')
        if self.raWidthList:   rawRealList = json.loads('['+self.raWidthList+']')

        if self.decList:       decRealList = json.loads('['+self.decList+']')
        if self.decWidthList:  decwRealList = json.loads('['+self.decWidthList+']')

        if self.gpstimeList:   gpstimeRealList = json.loads('['+self.gpstimeList+']')
        if self.durationList:  durationRealList = json.loads('['+self.durationList+']')

        # is there anything in the ra list? 
        nList = len(raRealList)
        if nList > 0: 
            if decRealList and len(decRealList) != nList:
                raise ValueError('RA and Dec lists are different lengths.')
            if gpstimeRealList and len(gpstimeRealList) != nList:
                raise ValueError('RA and GPS lists are different lengths.')

        # is there anything in the raWidth list? 
        mList = len(rawRealList)
        if mList > 0:
            if decwRealList and len(decwRealList) != mList:
                raise ValueError('RAwidth and Decwidth lists are different lengths.')
            if durationRealList and len(durationRealList) != mList:
                raise ValueError('RAwidth and Duration lists are different lengths.')

            # There can be 1 width for the whole list, or one for each ra/dec/gps 
            if mList != 1 and mList != nList:
                raise ValueError('Width and duration lists must be length 1 or same length as coordinate lists')
        else:
            mList = 0

        ramin = 360.0
        ramax = 0.0
        decmin = 90.0
        decmax = -90.0
        gpsmin = 100000000000
        gpsmax = 0
        for i in range(nList):
            try:
                ra = float(raRealList[i])
            except:
                raise ValueError('Cannot read RA list element %d of %s'%(i, self.raList))
            try:
                dec = float(decRealList[i])
            except:
                raise ValueError('Cannot read Dec list element %d of %s'%(i, self.decList))
            try:
                gps = int(gpstimeRealList[i])
            except:
                raise ValueError('Cannot read GPStime list element %d of %s'%(i, self.gpstimeList))

            # the widths list can have 1 member to cover all, or one for each
            if mList==1: j=0
            else       : j=i

            try:
                w = float(rawRealList[j])/2
            except:
                raise ValueError('Cannot read raWidth list element %d of %s'%(i, self.raWidthList))

            # evaluate bounding box
            if ra-w < ramin: ramin = ra-w
            if ra+w > ramax: ramax = ra+w

            try:
                w = float(decwRealList[j])/2
            except:
                raise ValueError('Cannot read raWidth list element %d of %s'%(i, self.decWidthList))

            # evaluate bounding box
            if dec-w < decmin: decmin = dec-w
            if dec+w > decmax: decmax = dec+w

            try:
                w = int(durationRealList[j])/2
            except:
                raise ValueError('Cannot read duration list element %d of %s'%(i, self.durationList))

            # evaluate bounding box
            if gps-w < gpsmin: gpsmin = gps-w
            if gps+w > gpsmax: gpsmax = gps+w

        # Make sure the min/max ra and dec are within bounds:
        ramin  = max(0.0,   ramin)
        ramax  = min(360.0, ramax)
        decmin = max(-90.0, decmin)
        decmax = min(90.0,  decmax)

        if nList>0:
            self.ra       = (ramin + ramax)/2
            self.dec      = (decmin + decmax)/2
            self.gpstime  = (gpsmin+gpsmax)/2
        if mList>0:
            self.raWidth  = ramax-ramin
            self.decWidth = decmax-decmin
            self.duration = gpsmax-gpsmin
        return True