Beispiel #1
0
    def __init__(self, schema = None):

        self.schema = schema if schema is not None else self.getDefaultSchema()

        self.archiveDB = ArchiveDB()
        self.astridDB  = AstridDB(dbname = "turtle")

        self.uri = "http://www.nrao.edu/namespaces/nrao"
        self.nsprefix = 'nrao'
Beispiel #2
0
class CurrentObsXML:

    """
    This class is responsible for gathering information on what is 
    currently observing on the GBT, and providing this information
    in a valid XML format, as specified by a schema.
    """

    def __init__(self, schema = None):

        self.schema = schema if schema is not None else self.getDefaultSchema()

        self.archiveDB = ArchiveDB()
        self.astridDB  = AstridDB(dbname = "turtle")

        self.uri = "http://www.nrao.edu/namespaces/nrao"
        self.nsprefix = 'nrao'

    def getXMLString(self):
        "Returns (status, XMLString) of current observations"
        info = self.getCurrentObsInfo()
        xmlDoc = self.getXMLDoc(info)
        # validate
        #print etree.tostring(xmlDoc)
        if not self.validate(xmlDoc):
           return (False, None)

        return (True, self.xmlDoc2str(xmlDoc))
           

    def getXMLDoc(self, info):
        "Returns xml tree based off dict of current obs. info"
        # KLUGE: lxml doesn't put the namespace prefixes in, so we have to do 
        # this by hand; but 'nrao:' is invalid, so sticking in 'nrao-' now
        # then replacing '-' with ':'
        nsmap = {self.nsprefix : self.uri}
        root = etree.Element("%s-currently_observing" % self.nsprefix, nsmap=nsmap) #, telescope="GBT")
        # shucks, order might matter
        keys = ["telescope", "proposal_code", "proposal_title", "proposal_abstract", "PI_name", "PI_institution", "source_name", "source_ra", "source_dec"]
        for key in keys:
            subel = etree.Element("%s-%s" % (self.nsprefix, key))
            subel.text = info[key]
            root.append(subel)
        return root

    def validate(self, xmlDoc):
        "Is the given xml valid according to our schema?"

        # first, prepare the schema
        f = StringIO(self.schema)
        xmlschema_doc = etree.parse(f)
        xmlschema = etree.XMLSchema(xmlschema_doc)

        # prepare the xmlDoc
        xmlStr = etree.tostring(xmlDoc)
        xmlStr = self.prepareXmlNamespace(xmlStr)
        xmlStrIo = StringIO(xmlStr)
        doc = etree.parse(xmlStrIo)

        # and validate
        return xmlschema.validate(doc)

    def xmlDoc2str(self, xmlDoc):
        return self.prepareXmlNamespace(etree.tostring(xmlDoc))

    def prepareXmlNamespace(self, xmlStr):
        "KLUGE: get the namepsace prefixes in there!"
        # by replacing the appropriate - with :
        xmlStr = xmlStr.replace("<nrao-", "<nrao:")
        xmlStr = xmlStr.replace("</nrao-", "</nrao:")
        return xmlStr

    def getMostRecentScienceProject(self, now = None):
        "We want the most recent science, not maintenance, testing, etc."

        if now is None:
            now = datetime.datetime.utcnow()

        # get all periods that have started in the past (the first of these is the current period)
        ps = Period.objects.filter(start__lt = now, state__abbreviation = 'S').order_by('-start')

        # go through these until you find a 'science' period
        sciencePeriod = None
        for p in ps:
            if self.isScienceObserving(p):
                sciencePeriod = p
                break

        return sciencePeriod.session.project if sciencePeriod is not None else None        

    def isScienceObserving(self, period):
        "Is this period for science and other factors?"
        p = period.session.project
        # make sure:
        #  * its science and not things like testing, maintenance, etc.
        #  * it has an entry in the PST: note that this works since all older projects
        #    that might not have an associated PHT proposal (that in turn gives the
        #    link to the PST) are completed, and shouldn't come up here.
        return p.is_science() and p.get_pst_proposal_id() is not None 
        
    def getCurrentObsInfo(self, project = None, start = None, useArchive = True):
        "Returns the desired info in a dict."

        # Init the info we need to get
        pcode = title = abstract = pi = piInst = piName = srcName = "unknown"
        ra = dec = '0.0'
        gbt = 'GBT'

        # get the current project observing
        if project is None:
            project = self.getMostRecentScienceProject(now = start)
            if project is None:
                # bail!
                return dict(proposal_code=pcode
                  , proposal_title=title
                  , proposal_abstract=abstract
                  , PI_name=piName
                  , PI_institution=piInst
                  , source_name=srcName
                  , source_ra=ra
                  , source_dec=dec
                  , telescope = gbt
                   )

        # get all you can from DSS DB
        pcode = self.createProjectCode(project.pcode)
        title = project.name
        abstract = project.abstract
        pi = project.principal_investigator()
        if pi is not None:
            piName = pi.display_name() 
            uInfo = pi.getStaticContactInfo()
            if len(uInfo['affiliations']) > 0:
                piInst = uInfo['affiliations'][0]


        # get the rest 
        if useArchive:
            # dont' try anything if you can't find the correct astrid code
            projectCode = self.astridDB.dssCode2astridCode(project.pcode)
            if self.astridDB.astridCodeExists(projectCode):
                srcName, ra, dec = self.archiveDB.getSourceInfo(projectCode
                                                              , start = start)
                ra = str(deg2rad(ra))
                dec = str(deg2rad(dec))

        return dict(proposal_code=pcode
                  , proposal_title=title
                  , proposal_abstract=abstract
                  , PI_name=piName
                  , PI_institution=piInst
                  , source_name=srcName
                  , source_ra=ra
                  , source_dec=dec
                  , telescope = gbt
                   )

    def createProjectCode(self, pcode):
        "Ex: GBT13B-001 -> 13B-001"

        # we need to convert project codes of the format:
        # <telescope><semester>-nnn
        #   where:
        #     <telescope> is something like GBT or VLBA
        #     <semester> is something like 12B, etc.
        #     nnn - is 001 through 999

        dash = pcode.find('-')
        if dash == -1:
            # this project code is not of the format '<tele><sem>-nnn'
            return pcode
        
        # check the semester
        sem = pcode[dash-3:dash]
        try:
            _ = int(sem[:2])
        except:
            return pcode
        if sem[2] not in ['A', 'B', 'C']:
            return pcode

        # check the number nnn
        try:
            _ = int(pcode[dash+1:])
        except:
            return pcode

        # okay, I think we can safely convert this project code now
        return pcode[dash-3:]

    def getDefaultSchema(self):
        sch = """<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
  version         = "1.0"
  xmlns:xs        = "http://www.w3.org/2001/XMLSchema"
  targetNamespace = "http://www.nrao.edu/namespaces/nrao"
  xmlns:nrao      = "http://www.nrao.edu/namespaces/nrao"
  elementFormDefault = "qualified">

 <xs:simpleType name="telescopeType">
  <xs:restriction base="xs:string">
   <xs:enumeration value="ALMA"/>
   <xs:enumeration value="VLA"/>
   <xs:enumeration value="VLBA"/>
   <xs:enumeration value="GBT"/>
   <xs:enumeration value="other"/>
  </xs:restriction>
 </xs:simpleType>

 <xs:element name="currently_observing">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="telescope" type="nrao:telescopeType"/>
    <xs:element name="proposal_code" type="xs:string"/>
    <xs:element name="proposal_title" type="xs:string" minOccurs="0"/>
    <xs:element name="proposal_abstract" type="xs:string" minOccurs="0"/>
    <xs:element name="PI_name" type="xs:string" minOccurs="0"/>
    <xs:element name="PI_institution" type="xs:string" minOccurs="0"/>
    <xs:element name="source_name" type="xs:string" minOccurs="0"/>
    <xs:element name="source_ra" type="xs:double"/>
    <xs:element name="source_dec" type="xs:double"/>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema>"""
        return sch