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

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

fixes to object property pattern and validation errors. last commit before new egg

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