source: CMIP6dreq/trunk/dreqPy/overviewTabs.py @ 1271

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/CMIP6dreq/trunk/dreqPy/overviewTabs.py@1271
Revision 1271, 11.6 KB checked in by mjuckes, 12 months ago (diff)

fixed python 3 compatibility issue regarding obsolete use of string module

Line 
1import collections, os
2import xlsxwriter
3
4try:
5  import dreq
6  import scope_utils
7except:
8  import dreqPy.dreq as dreq
9  import dreqPy.scope_utils as scope_utils
10
11jsh='''
12<link type="text/css" href="/css/dreq.css" rel="Stylesheet" />
13'''
14
15def vfmt( x ):
16            if x < 1.e9:
17              s = '%sM' % int( x*1.e-6 )
18            elif x < 1.e12:
19              s = '%sG' % int( x*1.e-9 )
20            elif x < 1.e13:
21              s = '%3.1fT' % ( x*1.e-12 )
22            elif x < 1.e15:
23              s = '%3iT' % int( x*1.e-12 )
24            elif x < 1.e18:
25              s = '%3iP' % int( x*1.e-15 )
26            else:
27              s = '{:,.2f}'.format( x*1.e-9 ) 
28            return s
29
30class c1(object):
31  def __init__(self):
32    self.a = collections.defaultdict( int )
33
34class c2(object):
35  def __init__(self):
36    self.a = collections.defaultdict( list )
37
38hmap0 = {'CMIP6':'Historical'}
39class r1(object):
40  infoLog = collections.defaultdict( list )
41  def __init__(self,sc,mt_tables,tiermax=1,pmax=1,only=False,vols=None,fnm='new',msgLevel=0):
42    self.mt_tables = mt_tables
43    self.msgLevel = msgLevel
44
45    self.fnm = fnm
46    assert vols == None or type(vols) == type( () ), 'vols argument must be none or tuple of length 2: %s' % type(vols)
47    self.dq = sc.dq
48    self.mips = ['CMIP'] + scope_utils.mips
49    self.mipsp = self.mips[:-4]
50    self.sc = sc
51    self.pmax=pmax
52    self.efnsfx = ''
53    if sc.gridPolicyDefaultNative:
54        self.efnsfx = '_dn'
55    self.cc = collections.defaultdict( c1 )
56    self.ee = {}
57    for m2 in self.mipsp + ['TOTAL',]:
58        xx = [i for i in self.dq.coll['experiment'].items if i.mip == m2]
59        self.ee[m2] = xx
60
61    if vols != None:
62      assert len(vols) == 4, 'vols must be a tuple of length 4 (containing dictionaries ...): %s' % len(vols)
63      self.tiermax = sc.tierMax
64      vmm, vme, vmmt, vue = vols
65      for m in vmm:
66        for m2 in vmm[m]:
67          self.cc[m].a[m2] = vmm[m][m2]
68          if m2 != 'Unique':
69            self.cc[m].a['TOTAL'] += vmm[m][m2]
70
71      for m in vme:
72        for e in vme[m]:
73          i = sc.dq.inx.uid[e]
74          if i._h.label == 'experiment':
75            self.cc[m].a[i.label] = vme[m][e]
76
77      for m in vue:
78        for e in vue[m]:
79          i = sc.dq.inx.uid[e]
80          if i._h.label == 'experiment':
81            self.cc['_%s' % m].a[i.label] = vue[m][e]
82
83      for m in vmmt:
84        for m2,t in vmmt[m]: 
85           self.cc['_%s_%s' % (m,m2)].a[t] = vmmt[m][(m2,t)]
86           if m2 != 'Unique':
87             self.cc['_%s_%s' % (m,'TOTAL')].a[t] += vmmt[m][(m2,t)]
88           self.makeMMhtml(m,m2)
89        self.makeMMhtml(m,'TOTAL')
90
91      self.writeMips(True)
92      return
93    self.mode = 'def'
94
95    self.tiermax=tiermax
96    sc.setTierMax( tiermax )
97    tabs = self.mt_tables( sc )
98
99    mipsToDo = self.mips + ['TOTAL',]
100    assert 'SolarMIP' not in mipsToDo, 'SolarMIP error: %s ' % str(mipsToDo)
101    assert 'SolarMIP' not in self.mipsp, 'SolarMIP error: %s ' % str(self.mipsp)
102    if only != False:
103      mipsToDo = [only,]
104    for m in mipsToDo:
105      if m == 'TOTAL':
106        l1 = sc.rqiByMip( set( self.mips ) )
107      else:
108        l1 = sc.rqiByMip( m )
109
110      self.cc[m].dd = {}
111      tabs.accReset()
112##
113## need to check this option, and add a template for a view summarising the experiments for each mip-mip combinations
114##
115## sss=True not yet tested
116##
117      for m2 in self.mipsp + ['TOTAL',]:
118        sss = True
119        if sss:
120          for i in xx:
121            tabs.doTable(m,l1,i.uid,pmax,self.cc,acc=False)
122          tabs.doTable(m,l1,m2,pmax,self.cc)
123          if only == False:
124            self.makeMMhtml(m,m2)
125        else:
126          tabs.doTable(m,l1,m2,pmax,self.cc)
127
128    if only == False:
129      self.writeMips(sss)
130
131  def makeMMhtml(self,m,m2):
132    """Make a html page for data requested by MIP 'm' from MIP 'm2' experiments"""
133    if self.fnm == 'new':
134      fss = 'expt_%s_%s_%s_%s%s.html' % (m,m2,self.tiermax, self.pmax,self.efnsfx)
135    else:
136      fss = '%s-%s_%s_%s.html' % (m,m2,self.tiermax, self.pmax)
137    kc = '_%s_%s' % (m,m2)
138    self.infoLog[ 'INFO.mmhtml.00001' ].append( ' %s, %s' % (kc,len( self.cc[kc].a.keys() ) ) )
139    ##print ('INFO.mmhtml.00001: %s, %s' % (kc,len( self.cc[kc].a.keys() ) ) )
140    if len( self.cc[kc].a.keys() ) == 0:
141      return
142    if not os.path.isdir( 'tabs03' ):
143      print ( 'WARNING.makeMMhtml: creating directory for html files: tabs03' )
144      os.mkdir( 'tabs03' )
145    oo = open( 'tabs03/%s' % fss, 'w' )
146    ttl = 'Data requested by %s from %s experiments (tier %s, priority %s)' % (m,m2,self.tiermax,self.pmax)
147    jsh = ''
148    pream = '<h1>%s</h1>\n' % ttl
149    if self.efnsfx == '_dn':
150      pream += '<p>Using the native ocean grid when no explicit preference is specified in the request.</p>\n'
151    if self.fnm == 'new':
152      pream += '<p>All variables in one <a href="../data/tabs02/cmvmm_%s_%s_%s_%s%s.xlsx">Excel file</a></p>\n' % (m,m2,self.tiermax, self.pmax,self.efnsfx)
153    else:
154      pream += '<p>All variables in one <a href="../data/tabs02/%s-%s_%s_%s.xlsx">Excel file</a></p>\n' % (m,m2,self.tiermax, self.pmax)
155    pream += '<ul>'
156    kc = '_%s_%s' % (m,m2)
157    for k in sorted( self.cc[kc].a.keys() ):
158      pream += '<li>%s: %s</li>\n' % (k,vfmt(self.cc[kc].a[k]*2.) )
159    pream += '</ul>'
160
161    bdy = pream + '<table>\n'
162    bdy += '<tr><th>Experiment</th><th>Volume (and link to variable lists)</th></tr>\n'
163    thisee = self.cc[m].a
164    pref = 'cmvme'
165    if  m2 in ['TOTAL']:
166      labs = sorted( [x for x in self.cc[m].a.keys() if x in self.sc.exptByLabel] )
167    elif m2 in ['Unique']:
168      labs = sorted( [x for x in self.cc['_%s' % m ].a.keys() if x in self.sc.exptByLabel] )
169      thisee = self.cc['_%s' % m].a
170      pref = 'cmvume'
171    else:
172      try:
173        assert m2 in self.ee, 'Argument m2:%s not in self.ee' % m2
174        assert m in self.cc, 'Argument m:%s not in self.cc' % m
175        labs = sorted( [i.label for i in self.ee[m2] if (i.label in self.cc[m].a and i._h.label == 'experiment')] )
176      except:
177        print ( 'SEVERE: failed to create labs array' )
178        labs = []
179
180    for ilab in labs:
181        x = thisee[ilab]*2.
182        if x > 0:
183          s = vfmt( x )
184          if self.fnm == 'new':
185            bdy += '<tr><td>%s</td><td><a href="../data/tabs02/%s_%s_%s_%s_%s%s.xlsx">%s</a></td></tr>\n' % (ilab,pref,m,ilab,self.tiermax, self.pmax,self.efnsfx,s)
186          else:
187            bdy += '<tr><td>%s</td><td><a href="../data/tabs02/%s-%s_%s_%s.xlsx">%s</a></td></tr>\n' % (ilab,m,ilab,self.tiermax, self.pmax,s)
188
189    bdy += '</table>\n'
190
191    oo.write( self.dq.pageTmpl % (ttl, jsh, '../', '../index.html', bdy ) )
192    oo.close()
193   
194  def writeMips(self,sss=False):
195
196    oo = open( 'tab01_%s_%s.texfrag' % (self.tiermax,self.pmax), 'w' )
197    mmh = []
198    mhdr = [ '\\rot{80}{%s}' % hmap0.get(m,m) for m in self.mipsp + ['TOTAL',]]
199    mhdrh = [ '<th><div><span>%s</span></div></th>' % hmap0.get(m,m) for m in self.mipsp + ['TOTAL','Unique','CALC']]
200    oo.write( ' & '.join(['',] + mhdr ) + '\\\\ \n\\hline\n' )
201    mmh.append( '<table>\n<tr class="rotate">' + ''.join(['<th></th>',] + mhdrh ) + '</tr>\n' )
202    htmltmpl_head = '<html><body>\n' 
203
204##
205## the "oo1" tables need a little more work to be useful
206## not supported by the "vols" entry option of this class
207##
208    doOo1 = False
209
210    for m in self.mips + ['TOTAL',]:
211      ll = [m,]
212      llh = [m,]
213      ttl = 0.
214      cct = collections.defaultdict( int )
215      xt = 0.
216      for m2 in self.mipsp + ['TOTAL','Unique']:
217       if doOo1:
218         if m2 in self.cc[m].dd:
219           oo1 = open( 'html/tt/rq-%s-expt-%s.html' % (m,m2), 'w' )
220           oo1.write( htmltmpl_head  )
221           oo1.write( '''<div class="demo">\n<div id="tabs">\n<ul>''' )
222           ks = sorted( self.cc[m].dd[m2].keys() )
223           for t in ks:
224              this1 = '<li><a href="#tabs-%s">%s</a></li>' % (t,t )
225              oo1.write( this1 )
226           oo1.write( '</ul>' )
227           for k in ks:
228               oo1.write( '<div id="tabs-%s">\n' % k )
229               oo1.write( '<table><tr>' )
230               for h in ['Frequency','Table','Label','Title','Description','UID' ]:
231                 oo1.write( '<td>%s</td>' % h )
232               for t in self.cc[m].dd[m2][k]:
233                 oo1.write( '\n</tr><tr>\n' )
234                 oo1.write( ''.join( ['<td>%s</td>' % x for x in t ] ) + '\n' )
235               oo1.write( '</tr></table></div>\n' )
236   
237           oo1.write( '</body></html>' )
238           oo1.close()
239       
240       if self.cc[m].a[m2] == 0:
241          ll.append( '' )
242          llh.append( '' )
243       else:
244          try:
245            if m2 == 'TOTAL':
246              x = xt
247            else:
248              x = self.cc[m].a[m2]*2.
249              xt += x
250
251            s = vfmt( x )
252            kc = '_%s_%s' % (m,m2)
253            if m2 == 'TOTAL':
254              sm = '; '.join( ['%s: %s' % (k,vfmt(cct[k]*2.)) for k in sorted( cct ) ] )
255              if self.msgLevel > 1:
256                print ( 'INFO.overviewTabs.01001: %s, %s' % (m,cct) )
257              s1 = '<b><span title="%s">%s</span></b>' % (sm,s)
258              s = '<b>%s</b>' % s
259            else:
260               for k in self.cc[kc].a.keys():
261                cct[k] += self.cc[kc].a[k]
262            ll.append( s )
263            sm = '; '.join( ['%s: %s' % (k,vfmt(self.cc[kc].a[k]*2.)) for k in sorted( self.cc[kc].a.keys() ) ] )
264
265            if sss:
266              if self.fnm == 'new':
267                fss = 'expt_%s_%s_%s_%s%s.html' % (m,m2,self.tiermax, self.pmax,self.efnsfx)
268              else:
269                fss = '%s-%s_%s_%s.html' % (m,m2,self.tiermax, self.pmax)
270              llh.append( '<a title="By table: %s" href="tabs03/%s">%s</a>' % (sm,fss,s) )
271            else:
272              llh.append( '<a title="By table: %s" href="data/tabs02/%s">%s</a>' % (sm,fn,s) )
273          except:
274            print ( 'Failed to compute element: %s,%s  %s' % (m,m2, str(self.cc[m].a[m2]) ) )
275            raise
276      oo.write( ' & '.join(ll ) + '\\\\ \n\\hline\n' )
277      llh.append( '<a href="data/tabs02/requestVol_%s_%s_%s.xlsx">Workings</a>' % (m,self.tiermax, self.pmax) )
278      mmh.append( '<tr>' + ''.join(['<td>%s</td>' % x for x in llh] ) + '</tr>\n' )
279    mmh.append( '</table>' )
280    ttl = 'Data volume overview, upto tier %s and priority %s -- provisional' % (self.tiermax, self.pmax) 
281    if self.sc.gridPolicyDefaultNative:
282      defNat = 'For volume estimation, ocean data is assumed to be on the model native grid unless specifically requested on an interpolated grid'
283    else:
284      defNat = 'For volume estimation, ocean data is assumed to be on a regular 1-degree grid unless specifically requested on another grid (e.g. the native model grid)'
285    bdy = '''<h1>%(ttl)s</h1>
286<p>Data volumes are estimated for nominal model with 1 degree resolution and 40 levels in the atmosphere and 0.5 degrees with 60 levels in the ocean.  The "Requesting MIP" (rows) is the MIP specifying the data required to meet their scientific objectives. The "designing MIP" (columns) is the MIP specifying the experimental design. %(defNat)s <b>The figures below represent work in progress: there are still omissions and flaws, more details are on the
287<a href="https://earthsystemcog.org/projects/wip/CMIP6DataRequest" title="Data Request CoG page">Data Request home page</a>.</b></p>
288''' % {'ttl':ttl, 'defNat':defNat }
289    bdy += '\n'.join( mmh )
290    ooh = open( 'tab01_%s_%s%s.html' % (self.tiermax,self.pmax,self.efnsfx), 'w' )
291    ooh.write( self.dq.pageTmpl % (ttl, jsh, './', './index.html', bdy ) )
292    ooh.close()
293    oo.close()
294
295
296if __name__ == "__main__":
297  try:
298    import makeTables
299    import scope
300  except:
301    import dreqPy.scope as scope
302    import dreqPy.makeTables as makeTables
303  sc = scope.dreqQuery()
304  r = r1( sc, makeTables.tables, tiermax=1, pmax=1 )
305  r = r1( sc, makeTables.tables, tiermax=3, pmax=3 )
Note: See TracBrowser for help on using the repository browser.