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

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

01.00.30beta

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