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

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

01.00.29

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