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

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

01.00.28b1

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