source: CMIP6dreq/trunk/dreqPy/misc_utils.py @ 1324

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/CMIP6dreq/trunk/dreqPy/misc_utils.py@1324
Revision 1324, 12.2 KB checked in by mjuckes, 8 weeks ago (diff)

01.00.31beta

Line 
1import collections, os, sys
2import logging
3import time
4import difflib 
5
6python2 = True
7if sys.version_info[0] == 3:
8  python2 = False
9
10def vfmt( x ):
11            if x < 1.e9:
12              s = '%sM' % int( x*1.e-6 )
13            elif x < 1.e12:
14              s = '%sG' % int( x*1.e-9 )
15            elif x < 1.e13:
16              s = '%3.1fT' % ( x*1.e-12 )
17            elif x < 1.e15:
18              s = '%3iT' % int( x*1.e-12 )
19            elif x < 1.e18:
20              s = '%3iP' % int( x*1.e-15 )
21            else:
22              s = '{:,.2f}'.format( x*1.e-9 )
23            return s
24
25
26class mdiff(object):
27  """Compare a string against a list, using the difflib library, with an extension to look at case insensitive matches.
28     Lower case matches are weighted by 90% .. i.e. an exact match scores 1, an exact match after conversion to lower case score 0.90"""
29
30  def __init__(self,nmax=3,cut=0.3):
31    self.n = nmax
32    self.c = cut
33
34  def diff(self,s,targ):
35    if s in targ:
36      return (True, None)
37    targl = collections.defaultdict( set )
38    for x in targ:
39      targl[ x.lower() ].add( x )
40
41    l1 = difflib.get_close_matches(s,targ,self.n,self.c)
42    l1s = difflib.get_close_matches(s.lower(),targl,self.n,self.c)
43    if len( l1 ) == 0 and len(l1s) == 0:
44      return (False, 0)
45    cc = collections.defaultdict( set )
46    cc0 = collections.defaultdict( set )
47    for k in l1:
48      r = difflib.SequenceMatcher(None, s, k ).ratio()
49      cc0[k].add( r )
50      ##cc[r].add( k )
51
52    for k in l1s:
53      ##check for lower case matches ... scale by 0.9##
54      r = difflib.SequenceMatcher(None, s.lower(), k ).ratio()
55      r1 = 0.90*r
56      for x in targl[k]:
57        cc0[x].add( r1 )
58       ## cc[r1].add( x )
59
60## find maximum score for each term
61    for k,v in cc0.items():
62      cc[max(v)].add( k )
63
64    ks = sorted( cc.keys() )
65    ks.reverse()
66    ll = []
67    for k in  ks:
68      ll.append( (k,tuple( cc[k] )) )
69    return (False, len(ll), ll )
70
71  def prntprep(self,i,tt):
72          oo = []
73          if tt[1] == 0:
74            oo.append ( 'NOT FOUND: %s' % i )
75          else:
76            msg = []
77            for ix in tt[2]:
78              msg.append( '%s [%4.1f]' % (','.join( ix[1] ),ix[0]) )
79
80            oo.append( '----------------------------------------' )
81            if tt[1] == 1 and len(tt[2][0][1]) == 1:
82              oo.append ( 'NOT FOUND: %s:  SUGGESTION: %s' % (i,msg[0]) )
83            else:
84              oo.append ( 'NOT FOUND: %s:  SUGGESTIONS: %s' % (i,'; '.join( msg ) ) )
85            oo.append( '----------------------------------------' )
86          return oo
87         
88def setMlab( m ):
89      if type(m) == type(''):
90        if m == '_all_':
91          mlab = 'TOTAL'
92        else:
93          mlab = m
94      else:
95        ll = sorted( [x.lower() for x in list(m)] )
96        if len(ll) == 1:
97          mlab = list(m)[0]
98        else:
99          mlab='.'.join( [ x[:2].lower() for x in ll ] )
100      return mlab
101
102class dreqLog(object):
103  def __init__(self, dir='.'):
104    self.tstring2 = '%4.4i%2.2i%2.2i' % time.gmtime()[0:3]
105    self.logdir = dir
106    if not os.path.isdir( dir ):
107      os.mkdir(dir )
108      print ( 'dreqLog: making a new directory fr log files: %s' % dir )
109
110  def getLog(self,name,dir=None):
111    if dir == None:
112      dir = self.logdir
113    testLogFile = '%s/dreq_%s_%s.txt' % (dir,name,self.tstring2)
114    log = logging.getLogger(testLogFile)
115    fHdlr = logging.FileHandler(testLogFile,mode='w')
116    fileFormatter = logging.Formatter('%(message)s')
117    fHdlr.setFormatter(fileFormatter)
118    log.addHandler(fHdlr)
119    log.setLevel(logging.INFO)
120    return log
121
122def rankCMORvars(dq):
123  """Unused in 01.beta.32"""
124  cc = collections.defaultdict( set )
125  ee = {}
126  kd = 0
127  ff = {}
128  for ic in dq.coll['CMORvar'].items:
129    s = set()
130    r = set()
131    i = dq.inx.uid[ ic.vid ]
132    if i._h.label != 'remarks':
133      kk = '%s.%s' % (ic.mipTable, ic.label)
134      if i.title != ic.title:
135        print ( '%s: %s, %s' % (kk, ic.title, i.title) )
136        kd += 1
137      if ic.modeling_realm.find( ' ' ) != -1:
138         for x in ic.modeling_realm.split( ):
139            r.add( x.strip( ) )
140      elif ic.modeling_realm not in ['__unset__','']:
141          r.add( ic.modeling_realm )
142      if 'requestVar' in dq.inx.iref_by_sect[ic.uid].a:
143          for x in dq.inx.iref_by_sect[ic.uid].a['requestVar']:
144            s.add(x)
145
146    if len(s) > 0:
147      ee[kk] = r
148      ff[kk] = i
149      ss = sorted( [dq.inx.uid[x].priority for x in s] )
150      if len(ss) > 1:
151        kk = '%s-%s' % (ss[0],ss[1])
152        sn = dq.inx.uid[i.sn]
153        if sn._h.label == 'remarks':
154          kk += 'x'
155        cc[kk].add( i.label )
156    else:
157      print ( '%s not used' % i.label )
158  print ( kd )
159  return (cc,ee,ff)
160
161def rankVars(dq):
162  """Find the maximal priorities at which variables are requested ... to prioritise checking .. called by sm1"""
163  cc = collections.defaultdict( set )
164  ee = {}
165  ff = {}
166  for i in dq.coll['var'].items:
167    s = set()
168    r = set()
169    if 'CMORvar' in  dq.inx.iref_by_sect[i.uid].a:
170      for cmv in dq.inx.iref_by_sect[i.uid].a['CMORvar']:
171        ic = dq.inx.uid[cmv]
172        if ic.modeling_realm.find( ' ' ) != -1:
173          for x in ic.modeling_realm.split( ):
174            r.add( x.strip( ) )
175        elif ic.modeling_realm not in ['__unset__','']:
176          r.add( ic.modeling_realm )
177        if 'requestVar' in dq.inx.iref_by_sect[cmv].a:
178          for x in dq.inx.iref_by_sect[cmv].a['requestVar']:
179            s.add(x)
180
181    if len(s) > 0:
182      ee[i.label] = r
183      ff[i.label] = i
184      ss = sorted( [dq.inx.uid[x].priority for x in s] )
185      if len(ss) > 0:
186        kk = '%s' % (ss[0])
187        sn = dq.inx.uid[i.sn]
188        if sn._h.label == 'remarks':
189          kk += 'x'
190        cc[kk].add( i.label )
191    else:
192      print ( '%s not used' % i.label )
193  return (cc,ee,ff)
194
195def getExptSum(dq,mip,rqi):
196  """Return a dictionary of experiment uids keyed on MIPs, from list of request items (used in makeTables)"""
197  cc = collections.defaultdict( set )
198  for i in rqi:
199    es = dq.inx.uid[i.esid]
200    if es._h.label == 'experiment':
201      cc[es.mip].add(es.uid)
202    elif es._h.label in ['exptgroup','mip']:
203      if 'experiment' in dq.inx.iref_by_sect[i.esid].a:
204        for id in dq.inx.iref_by_sect[i.esid].a['experiment']:
205          ex = dq.inx.uid[id]
206          cc[ex.mip].add(id)
207
208  return cc
209
210class rqiSet(object):
211  """Unused in 01.beta.32"""
212  npy = {'1hrClimMon':24*12, 'daily':365, u'Annual':1, u'fx':0.01, u'1hr':24*365, u'3hr':8*365,
213       u'monClim':12, u'Timestep':100, u'6hr':4*365, u'day':365, u'1day':365, u'mon':12, u'yr':1,
214       u'1mon':12, 'month':12, 'year':1, 'monthly':12, 'hr':24*365, 'other':24*365,
215        'subhr':24*365, 'Day':365, '6h':4*365, '3 hourly':8*365, '':1, 'dec':0.1, 
216        '1hrCM':24*12, '1hrPt':24*365, '3hrPt':8*365, '6hrPt':4*365, 'monPt':12, 'monC':12, 'subhrPt':24*365, 'yrPt':1 }
217  def __init__(self,dq,rqi=None,byMip=None):
218    self.dq = dq
219    if rqi != None:
220      assert byMip == None, 'ERROR.rqiSet.001: Cannot have rqi and byMip both assigned'
221      self.rqi = rqi
222    elif byMip != None:
223      self.rqi = [i for i in dq.coll['requestItem'].items if i.mip == byMip]
224    else:
225      self.rqi = dq.coll['requestItem'].items
226
227    self.verbose = False
228    if self.verbose:
229      print ( 'INFO.rqiSet.00001: initialised, len(rqi) = %s' % len(self.rqi) )
230
231  def run(self,vsz,rqi=None,pmax=1,tiermax=1,plist=False):
232    self.exptVarSum(pmax=pmax,plist=plist,tiermax=tiermax)
233    self.exptVarVol(vsz,plist=plist,tiermax=tiermax)
234
235  def getVarList(self,rqi,pmax=1):
236    cc = collections.defaultdict( list )
237    for i in rqi:
238      rl = self.dq.inx.uid[i.rlid]
239      if 'requestVar' in self.dq.inx.iref_by_sect[rl.refid].a:
240        for id in self.dq.inx.iref_by_sect[rl.refid].a['requestVar']:
241          rq = self.dq.inx.uid[id]
242          if rq.priority <= pmax:
243            cc[rq.vid].append( (i.ny, i.nymax, i.nenmax,rl.grid,i.uid) )
244    ee = {}
245    for vid in cc.keys():
246      if len( cc[vid] ) == 1:
247        ee[vid] = cc[vid][0]
248      else:
249        ll = [x[0] for x in cc[vid] if x[0] > 0]
250        if len(ll) == 0:
251          ny = -1
252        else:
253          ny = max(ll)
254        ll = [x[1] for x in cc[vid] if x[1] > 0]
255        if len(ll) == 0:
256          nymax = -1
257        else:
258          nymax = max(ll)
259        ll = [x[2] for x in cc[vid] if x[2] > 0]
260        if len(ll) == 0:
261          nenmax = -1
262        else:
263          nenmax = max(ll)
264        ss = set( [x[3] for x in cc[vid]] )
265        rqil =  [x[4] for x in cc[vid] ] 
266        ee[vid] = (ny,nymax,nenmax,list(ss),rqil )
267
268    return ee
269
270  def exptVarSum(self,exptsOk=False,pmax=1,plist=True,tiermax=1):
271    if not exptsOk:
272      self.exptByMip(tiermax=tiermax)
273
274    self.exvars = {}
275    for m in sorted( self.expts.keys() ):
276      for i in self.expts[m]:
277        rqi = [self.dq.inx.uid[x] for x in self.exrqi[i] ]
278
279## obtain dictionary, keyed om CMORvar uid, of variables requested
280        ee = self.getVarList( rqi, pmax=pmax )
281        ex = self.dq.inx.uid[i]
282        if plist:
283          print ( 'exptVarSum: %s, %s, %s (%s)' % (m,ex.label,len( ee.keys() ), len( rqi)) )
284        self.exvars[i] = ee
285
286  def exptVarVol(self,vsz,plist=True,tiermax=1):
287    nttt = 0
288##
289## exvarvol is a dictionary of dictionaries. key 1: experiment uid.
290##                                           key 2: cmor variable uid
291##                               content: 5-tuple: ntot: floats requested
292##                                                    s: floats per time instant
293##                                                  npy: number of outputs per year
294##                                                   ny: number of years of output
295##                                                  nen: number of ensembles
296####################################################################################
297    self.exvarvol = {}
298    for m in sorted( self.expts.keys() ):
299      for i in self.expts[m]:
300        ee = self.exvars[i]
301        ex = self.dq.inx.uid[i]
302##
303## experiment has list of ensemble size (ensz) against tier (tier)
304## max ensz st. tier <= tiermax
305##
306        l = [x for x in ex.tier if x <= tiermax]
307        exensz = ex.ensz[len(l)-1]
308
309        cmvd = {}
310        nn = 0
311        nerr = 0
312        for k in ee:
313          cmv = self.dq.inx.uid[k]
314          if cmv._h.label == 'CMORvar':
315            s = vsz[cmv.stid]
316            npy = self.npy[cmv.frequency]
317            nyi = ee[k][0]
318            if ex.yps < 0:
319              ny = nyi
320            else:
321              ny = min( [ex.yps,nyi] )
322            ne = ee[k][2]
323            if ne < 0:
324              nen = exensz
325            else:
326              nen = min( [ne,exensz] )
327            ntot = s*npy*ny*nen
328##
329## need to do more on various options here
330##
331            cmvd[k] = (ntot,s,npy,ny,nen)
332            nn += ntot
333          else:
334            nerr += 1
335        if plist:
336          print ( 'exptVarVol: %s, %s, %s[%s]: %9.4fTb' % (m,ex.label,len( ee.keys() ), nerr, nn*2.*1.e-12) )
337        nttt += nn
338        self.exvarvol[i] = cmvd
339
340    if plist:
341      print ( 'TOTAL: %9.3fTb' % (nttt*2*1.e-12) )
342       
343  def exptByMip(self,tiermax=1):
344    cc = collections.defaultdict( list )
345    for i in self.rqi:
346      cc[i.mip].append( i )
347
348    ks = sorted( list( cc.keys() ) )
349    for k in ks:
350      self.getExptByThisMip(k,cc[k],tiermax=tiermax)
351
352  def getExptByThisMip(self,mip,rqi,tiermax=1):
353    self.expts = collections.defaultdict( set )
354    self.exrqi = collections.defaultdict( set )
355    for i in rqi:
356      es = self.dq.inx.uid[i.esid]
357
358## check to see if "treset" override is present and below tiermax
359      tover = False
360      if 'treset' in i.__dict__ and i.treset != '__unset__':
361        tover = i.treset <= tiermax
362       
363      if es._h.label == 'experiment':
364        if es.tier[0] <= tiermax or tover:
365          self.expts[es.mip].add(es.uid)
366          self.exrqi[es.uid].add( i.uid )
367      elif es._h.label in ['exptgroup','mip']:
368        if 'experiment' in self.dq.inx.iref_by_sect[i.esid].a:
369          for id in self.dq.inx.iref_by_sect[i.esid].a['experiment']:
370            ex = self.dq.inx.uid[id]
371            if ex.tier[0] <= tiermax or tover:
372              self.expts[ex.mip].add(id)
373              self.exrqi[id].add( i.uid )
374    ks = sorted( list( self.expts.keys() ) )
375    xx = ', '.join( ['%s: %s' % (k,len(self.expts[k])) for k in ks] )
376    print ( '%s:: %s' % (mip,xx) )
377
378class c1(object):
379  def __init__(self):
380    self.a = collections.defaultdict( int )
Note: See TracBrowser for help on using the repository browser.