source: TI02-CSML/trunk/csml2MolesStuff/csml2moles.py @ 1629

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI02-CSML/trunk/csml2MolesStuff/csml2moles.py@1629
Revision 1629, 8.5 KB checked in by domlowe, 13 years ago (diff)

moles roundtripping

Line 
1#!/usr/bin/env python
2
3import sys
4import csml.parser
5import cElementTree
6import elementtree.ElementTree as etree
7import datetime
8import molesWriter as MW
9#this is a fix to the  ElementTree namespace problem that namespaces are usually represented as ns0, ns1, ns2 etc.
10etree._namespace_map.update({
11        'http://www.opengis.net/om': 'om',  'http://www.opengis.net/gml': 'gml','http://ndg.nerc.ac.uk/csml' : 'csml', 'http://www.w3.org/1999/xlink':'xlink'})
12
13
14def _strToDate(ymd):
15    '''given a string in form '2006-01-01' returns a datetime object'''
16    return datetime.date(*map(int, ymd.split('-')))
17
18def _getEnvelopefromDataset(ds):
19    '''gets the bounding box from the feature collection'''
20    envelope= ds.featureCollection.boundedBy
21    return envelope
22
23def _parsefile(f):
24    tree = cElementTree.ElementTree(file=f)
25    dataset = csml.parser.Dataset()
26    dataset.fromXML(tree.getroot())
27    return dataset
28   
29
30class StandardName(object):
31    def __init__(self, somename):
32        '''given some name, attempt to resolve it into a standard name type structure. by stripping out any URLs etc'''
33        #types of names:
34        #myrandomvar
35        #http://some.namespace/localparams#somevar  #conventions?
36        #http://some.namespace/something#somevar  # standard name
37        #from these extract text (description), termid and vocabid where possible.       
38        #for starters split at '#'
39        #this can't be finalised till we agree on a convention.
40
41        sections=somename.split('#')
42        self.text=''
43        if len(sections)==2:
44            self.vocab=sections[0]
45            self.term=sections[1]
46        else:
47            self.term=somename
48            self.vocab=''
49
50class EnvelopeAggregator(object):
51    def __init__(self,envelope):
52        '''start with aggregated envelope equal to the initialising envelope
53        envelope must be of type csml.parser.EnvelopeWithTimePeriod'''
54        self.envelope=envelope
55        self.minX=self.envelope.lowerCorner.vals.split()[0]
56        self.minY=self.envelope.lowerCorner.vals.split()[1]
57        self.maxX=self.envelope.upperCorner.vals.split()[0]
58        self.maxY=self.envelope.upperCorner.vals.split()[1]
59        self.t1= _strToDate(self.envelope.timePosition)
60        self.t2= _strToDate(self.envelope.timePosition)
61 
62    def _compareLowerCorners(self,lowerCorner):
63        minX,minY=lowerCorner.vals.split()[0],lowerCorner.vals.split()[1]
64        if float(minX) < float(self.minX):
65            self.envelope.lowerCorner.vals=str(minX +' '+ self.minY)
66            self.minX=minX
67        if float(minY) < float(self.minY):
68            self.envelope.lowerCorner.vals=str(self.minX +' '+ minY)
69            self.minY=minY
70           
71    def _compareUpperCorners(self,upperCorner):
72        maxX,maxY=upperCorner.vals.split()[0],upperCorner.vals.split()[1]
73        if float(maxX) > float(self.maxX):
74            self.envelope.upperCorner.vals=str(maxX +' '+ self.maxY)
75            self.maxX=maxX
76        if float(maxY) > float(self.maxY):
77            self.envelope.upperCorner.vals=str(self.maxX +' '+ maxY)
78            self.maxY=maxY
79           
80    def _compareLowerTimes(self,timepos):
81        t=_strToDate(timepos)
82        if t<self.t1:
83            self.t1=t
84       
85    def _compareUpperTimes(self,timepos):
86        t=_strToDate(timepos)
87        if t>self.t2:
88            self.t2=t
89   
90    def compareEnvelope(self,envtocheck):
91        '''compares new envelope, and if necessary changes the aggregated envelope.'''
92        if envtocheck.srsName!=self.envelope.srsName:
93            print 'Can currently only perform aggregation within the same spatio-temporal reference system.'
94            sys.exit()
95        else: 
96            self._compareLowerCorners(envtocheck.lowerCorner)
97            self._compareUpperCorners(envtocheck.upperCorner)
98            self._compareLowerTimes(envtocheck.timePosition)
99            self._compareUpperTimes(envtocheck.timePosition2)
100   
101    def getAggregatedEnvelope(self):
102        self.envelope.timePosition=str(self.t1)  #convert from datetime types
103        self.envelope.timePosition2=str(self.t2)
104        return self.envelope
105
106
107def main(args=None):
108    '''Get command line arguments, should be an ID scheme for the moles document and paths to csml files
109    i,e, python  csml2moles.py badc.nerc.ac.uk document123 csmlfile1.xml csmlfile2.xml csmlfile3.xml
110    main() will aggregate the spatial and temporal bounding box across all the featureCollections.
111    Currently only one featureCollection per csml file is supported
112   
113    TODO: This should be extended to handle directories of files
114    TODO: CSML files may be stored in exist '''
115    repository = sys.argv[1]
116    identifier= sys.argv[2]
117
118    if args:
119        sys.argv =args
120    csmlfilelist= sys.argv[3:]
121
122    # MOLES skeleton document:
123    M=MW.MolesDoc()
124    M._createClasses()
125   
126    #set up coverage envelope aggragator with envelope from first file:
127    dataset=_parsefile(csmlfilelist[0])
128    env=_getEnvelopefromDataset(dataset)
129    aggregator=EnvelopeAggregator(env)
130 
131   
132    #set up lists to hold stuff
133    schemeIdentifiers=[]
134    repositoryIdentifiers=[]
135    localIdentifiers=[]
136    parameterSummaries=[]
137   
138    #for each file:
139    for f in csmlfilelist:
140        #parse file:
141        dataset=_parsefile(f)
142        #compare envelope:
143        aggregator.compareEnvelope(_getEnvelopefromDataset(dataset))
144        #get other things:
145        schemeIdentifiers.append('NDG-A0')
146        repositoryIdentifiers.append('badc.nerc.ac.uk')
147        localIdentifiers.append(f)
148        #create parameter summaries:
149        #print dir(dataset.featureCollection)
150       
151        for feature in dataset.featureCollection.members:
152            if hasattr(feature.parameter, 'href'):
153                sn=StandardName(feature.parameter.href)
154                if hasattr(feature, 'description'):
155                    sn.text=feature.description
156            VTID=M.dgValidTermID(ParentListID=sn.vocab, TermID=sn.term)
157           
158            SPM=M.dgStdParameterMeasured(dgValidTerm= sn.text, dgValidTermID=VTID)
159            RDP=M.dgRangeDataParameter(HighValue='', LowValue='')
160            PS  = M.dgParameterSummary(dgRangeDataParameter=RDP, dgStdParameterMeasured=SPM)
161            parameterSummaries.append(PS)
162    #get aggregated envelope:
163    finalEnvelope=aggregator.getAggregatedEnvelope()
164    limitN=finalEnvelope.upperCorner.vals.split()[0]
165    limitS=finalEnvelope.lowerCorner.vals.split()[0]
166    limitE=finalEnvelope.upperCorner.vals.split()[1]
167    limitW=finalEnvelope.lowerCorner.vals.split()[1]
168    #get other aggregations:
169   
170
171   
172    ''' The MOLES document:
173    create your moles doc by setting attributes of "M.className"
174    the classNames used must be declared in molesWriter.MolesDoc.classList'''
175   
176    #MetaData ID
177    dgMID=M.dgMetadataID(schemeIdentifier='NDG-B0', repositoryIdentifier=repository, localIdentifier=identifier)
178   
179    #create data granules
180    datagranules=[]
181    for i, file in enumerate(csmlfilelist):
182        DMid=M.dataModelID(schemeIdentifier=schemeIdentifiers[i], repositoryIdentifier=repositoryIdentifiers[i],localIdentifier= localIdentifiers[i])
183        DG  = M.dgDataGranule(dataModelID=DMid)
184        datagranules.append(DG)
185
186    #create coverage
187    dgBB=M.dgBoundingBox(LimitNorth = limitN, LimitSouth=limitS,LimitEast=limitE, LimitWest=limitW)
188    dgSc=M.dgSpatialCoverage(dgBoundingBox=dgBB)
189    dgTc=M.dgTemporalCoverage()
190    dgST=M.dgSpatioTemporalCoverage(dgSpatialCoverage = dgSc, dgTemporalCoverage=dgTc)
191    dgCv=M.dgCoverage(dgSpatioTemporalCoverage=dgST)
192   
193    #create data summary:
194    DS = M.dgDataSummary(dgCoverage=dgCv, dgParameterSummary=parameterSummaries)
195    #create data entity:
196    dgDE= M.dgDataEntity(dgDataGranule=datagranules, dgDataSummary=DS)
197   
198    #create metadata description:
199    mdID=M.metadataDescriptionID(schemeIdentifier='1',repositoryIdentifier='2', localIdentifier='3')
200    dgMD=M.dgMetadataDescription(metadataDescriptionID=mdID)
201    #create metadata record
202    dgMR=M.dgMetadataRecord(dgMetadataID=dgMID, dgDataEntity=dgDE, dgMetadataDescription=dgMD)
203    dgMeta=MW.dgMetadata(dgMetadataRecord=dgMR)
204
205    #round trip
206    #produce XML  and save to file
207    molestree=dgMeta.toXML()
208    moles=csml.parser_extra.PrettyPrint(molestree)
209    f=open('molesout.xml','w')
210    f.write(moles)
211    f.close()
212   
213   
214    #produce XML again (round trip)
215    tree=cElementTree.ElementTree(file='molesout.xml')
216    dgMeta=MW.dgMetadata()
217    dgMeta.fromXML(tree.getroot())
218    molestree=dgMeta.toXML()
219    moles=csml.parser_extra.PrettyPrint(molestree)
220    print moles   
221   
222if __name__=='__main__':
223    main()
Note: See TracBrowser for help on using the repository browser.