source: TI02-CSML/trunk/csml/csmllibs/csmlextra.py @ 2326

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI02-CSML/trunk/csml/csmllibs/csmlextra.py@2326
Revision 2326, 9.3 KB checked in by domlowe, 13 years ago (diff)

fixed beginPosition and endPosition in envelope

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#Stuff with nowhere better to go
2import random, datetime
3import string
4import csml.parser
5import sys
6
7def getRandomID():
8    #returns a random 8 character alphanumeric string that can be used as an internal identifier in a CSML document.
9    #the ID only needs to be unique within the document that it occurs, so this is sufficiently random
10    #to make a clash extremely unlikely. The string is alphanumeric but always begins with a letter. 
11    #Note: tested with 50000 ids and all were different
12    randomID=random.choice(string.letters)
13    for i in range(7):
14        randomID=randomID+random.choice(string.letters+string.digits)
15    return randomID
16
17def strToDate(ymd):
18    '''given a string in form '2006-01-01' returns a datetime object'''
19    return datetime.date(*map(int, ymd.split('-')))
20
21class EnvelopeAggregator(object):
22    def __init__(self,envelope):
23        '''start with aggregated envelope equal to the initialising envelope
24        envelope must be of type csml.parser.EnvelopeWithTimePeriod'''
25        self.envelope=envelope
26        self.minX=self.envelope.lowerCorner.CONTENT.split()[0]
27        self.minY=self.envelope.lowerCorner.CONTENT.split()[1]
28        self.maxX=self.envelope.upperCorner.CONTENT.split()[0]
29        self.maxY=self.envelope.upperCorner.CONTENT.split()[1]
30        self.t1= strToDate(self.envelope.beginPosition.CONTENT)
31        self.t2= strToDate(self.envelope.endPosition.CONTENT)
32 
33    def _compareLowerCorners(self,lowerCorner):
34        minX,minY=lowerCorner.CONTENT.split()[0],lowerCorner.CONTENT.split()[1]
35        if float(minX) < float(self.minX):
36            self.envelope.lowerCorner.CONTENT=str(minX +' '+ self.minY)
37            self.minX=minX
38        if float(minY) < float(self.minY):
39            self.envelope.lowerCorner.CONTENT=str(self.minX +' '+ minY)
40            self.minY=minY
41           
42    def _compareUpperCorners(self,upperCorner):
43        maxX,maxY=upperCorner.CONTENT.split()[0],upperCorner.CONTENT.split()[1]
44        if float(maxX) > float(self.maxX):
45            self.envelope.upperCorner.CONTENT=str(maxX +' '+ self.maxY)
46            self.maxX=maxX
47        if float(maxY) > float(self.maxY):
48            self.envelope.upperCorner.CONTENT=str(self.maxX +' '+ maxY)
49            self.maxY=maxY
50           
51    def _compareLowerTimes(self,timepos):
52        t=strToDate(timepos)
53        if t<self.t1:
54            self.t1=t
55       
56    def _compareUpperTimes(self,timepos):
57        t=strToDate(timepos)
58        if t>self.t2:
59            self.t2=t
60   
61    def compareEnvelope(self,envtocheck):
62        '''compares new envelope, and if necessary changes the aggregated envelope.'''
63        if envtocheck.srsName!=self.envelope.srsName:
64            print 'Can currently only perform aggregation within the same spatio-temporal reference system.'
65            sys.exit()
66        else: 
67            self._compareLowerCorners(envtocheck.lowerCorner)
68            self._compareUpperCorners(envtocheck.upperCorner)
69            self._compareLowerTimes(envtocheck.beginPosition.CONTENT)
70            self._compareUpperTimes(envtocheck.endPosition.CONTENT)
71   
72    def getAggregatedEnvelope(self):
73        self.envelope.beginPosition=csml.parser.csString(str(self.t1)) #convert from datetime types
74        self.envelope.endPosition=csml.parser.csString(str(self.t2)) 
75        return self.envelope
76
77
78
79def getSeqRule(nDims):
80        #returns a sequenceRule
81        #*****************very simplified version*****************
82        #This really needs more work to see if the +s and -s are correct. and the x/y/z s in right order
83        #nDims = spatial dimensions + time dimension
84       
85        #TODO CSML2 - rewrite this
86        if nDims == 2:
87                seq = "Linear"
88        elif nDims ==3:
89                seq = "+x+y"
90        elif nDims ==4:
91                seq = "+x+y+z"
92        else:
93                seq="not sure"
94        return seq
95       
96       
97def getMappingRule(nDims):
98        #TODO CSML2 - rewrite this
99        if nDims == 2:
100                mr = "+ gridI + series"
101        elif nDims ==3:
102                mr = "+ gridI + gridJ +series"
103        elif nDims ==4:
104                mr = "+ gridI + gridJ +gridK +series"
105        else:
106                mr="not sure"
107        return mr
108       
109
110def addEnvelope(fc, ffmap):
111    #adds EnvelopeWithTimePeriod to feature collection, based on the spatial extent of the features within.
112   
113    #process:   
114    #Extract the lat/lon and time extents from each representative file.    Create a temporary EnvelopeWithTimePeriod object, then use the EnvelopeAggregator class to aggregate into an envelope for the whole feature collection.
115   
116    #TODO, need to use the CRS catalogue to get these values
117    lonname='longitude'
118    latname='latitude'
119    timename='time'
120    srs='ndg:crs:xyt'
121   
122       
123    aggregator=None
124    for feature in fc.featureMembers:
125        if type(feature) is csml.parser.GridSeriesFeature:
126            tmax=None
127            tmin=None
128            for ord in feature.value.gridSeriesDomain.coordTransformTable.gridOrdinates:
129                if ord.coordAxisLabel.CONTENT==timename:
130                    tnewmin= strToDate(ord.coordAxisValues.coordinateList.CONTENT.split()[0].split('T')[0])
131                    tnewmax=strToDate( ord.coordAxisValues.coordinateList.CONTENT.split()[len(ord.coordAxisValues.coordinateList.CONTENT.split())-1].split('T')[0])
132                    if tmin ==None:
133                        tmin=tnewmin
134                    if tmax == None:
135                        tmax=tnewmax
136                    if tnewmin < tmin:
137                        tmin=tnewmin                   
138                    if tnewmax > tmax:
139                        tmax=tnewmax                     
140        if type(feature) is csml.parser.ProfileSeriesFeature:
141            tmax=None
142            tmin=None
143            for ord in feature.value.profileSeriesDomain.coordTransformTable.gridOrdinates:
144                if ord.coordAxisLabel.CONTENT==timename:
145                    tnewmin= strToDate(ord.coordAxisValues.coordinateList.CONTENT.split()[0].split('T')[0])
146                    tnewmax=strToDate( ord.coordAxisValues.coordinateList.CONTENT.split()[len(ord.coordAxisValues.coordinateList.CONTENT.split())-1].split('T')[0])
147                    if tmin ==None:
148                        tmin=tnewmin
149                    if tmax == None:
150                        tmax=tnewmax
151                    if tnewmin < tmin:
152                        tmin=tnewmin                   
153                    if tnewmax > tmax:
154                        tmax=tnewmax                     
155                       
156    for repfile in ffmap.getRepresentativeFiles():
157        minlon=None
158        maxlon=None
159        minlat=None
160        maxlat=None
161        f=repfile.getRepresentativeFileName()
162        DI=csml.csmllibs.csmldataiface.DataInterface()
163        DI=DI.getUnknownInterfaceType(f)
164        DI.openFile(f)
165        tmpDims=DI.getListOfAxes()
166        if lonname in tmpDims:
167            DI.setAxis(lonname)
168            vals=DI.getDataForAxis()
169            minlon=str(min(vals))
170            maxlon= str(max(vals))
171            if latname in tmpDims:
172                DI.setAxis(latname)
173                vals=DI.getDataForAxis()
174                minlat=str(min(vals))
175                maxlat= str(max(vals))                         
176        else:
177            tmpVars=DI.getListofVariables()
178            if lonname in tmpVars:
179                DI.setVariable(lonname)
180                vals=DI.getDataForVar()
181                minlon=str(min(vals))
182                maxlon= str(max(vals))
183                if latname in tmpVars:
184                    DI.setVariable(latname)
185                    vals=DI.getDataForVar()
186                    minlat=str(min(vals))
187                    maxlat= str(max(vals))
188           
189        env=csml.parser.EnvelopeWithTimePeriod()
190        env.lowerCorner=csml.parser.csString(minlon + ' ' + minlat)
191        env.upperCorner=csml.parser.csString(maxlon + ' ' + maxlat)
192        env.beginPosition=csml.parser.csString(tmin)
193        env.endPosition= csml.parser.csString(tmax)
194        env.srsName='srs tba'
195        if aggregator is None:
196            aggregator=EnvelopeAggregator(env)
197        else:
198            aggregator.compareEnvelope(env)
199    fcEnvelope=aggregator.getAggregatedEnvelope()
200    fcEnvelope.srsName=env.srsName 
201    fc.boundedBy=fcEnvelope
202    fc.boundedBy=env
203    return fc
204       
205       
206       
207       
208# a couple of string cleaning functions:
209#   don't think these are used now
210def cleanString1(messystring):
211        #removes outer brackets and changes commas to spaces
212        cleanstring = messystring[1:-1]
213        cleanstring = cleanstring.replace(',',' ')
214        #strip off first (time) dimension.
215        #note, this might need rethinking for other datasets
216        cleanstring = cleanstring[3:]
217        return cleanstring
218#       
219def cleanString(messystring):
220   # removes outer brackets and 's, but leaves commas.
221    cleanstring = messystring[1:-1]
222    cleanstring = cleanstring.replace("'",'')
223    #remove any carriage returns
224    cleanstring = cleanstring.replace("\n",'')
225    return cleanstring
226       
227def listify(item):
228    ''' listify checks if an item is a list, if it isn't it puts it inside a list and returns it. Always returns a list object'''
229    if type(item) is list:
230        return item
231    else:
232        return [item]       
233
234def main():
235    #test to check randomness of getRandomID()
236    idlist=[]
237    for j in range (500):
238        for i in range(100):
239            newid= getRandomID()
240            if newid in idlist:
241                print 'ID matched!!!'               
242                sys.exit()
243            else:               
244                idlist.append(newid)
245        print i * j
246    print 'done'
247   
248if __name__=="__main__":
249    main()
Note: See TracBrowser for help on using the repository browser.