|
| 1 | +# (C) British Crown Copyright 2018, Met Office |
| 2 | +# |
| 3 | +# This file is part of Iris. |
| 4 | +# |
| 5 | +# Iris is free software: you can redistribute it and/or modify it under |
| 6 | +# the terms of the GNU Lesser General Public License as published by the |
| 7 | +# Free Software Foundation, either version 3 of the License, or |
| 8 | +# (at your option) any later version. |
| 9 | +# |
| 10 | +# Iris is distributed in the hope that it will be useful, |
| 11 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | +# GNU Lesser General Public License for more details. |
| 14 | +# |
| 15 | +# You should have received a copy of the GNU Lesser General Public License |
| 16 | +# along with Iris. If not, see <http://www.gnu.org/licenses/>. |
| 17 | + |
| 18 | +""" |
| 19 | +Definitions of how Iris objects should be represented. |
| 20 | +
|
| 21 | +""" |
| 22 | + |
| 23 | + |
| 24 | +class CubeRepresentation(object): |
| 25 | + """ |
| 26 | + Produce representations of a :class:`~iris.cube.Cube`. |
| 27 | +
|
| 28 | + This includes: |
| 29 | +
|
| 30 | + * ``_html_repr_``: a representation of the cube as an html object, |
| 31 | + available in jupyter notebooks. |
| 32 | +
|
| 33 | + """ |
| 34 | + _template = """ |
| 35 | +<style> |
| 36 | + a.iris {{ |
| 37 | + text-decoration: none !important; |
| 38 | + }} |
| 39 | + .iris {{ |
| 40 | + white-space: pre; |
| 41 | + }} |
| 42 | + .iris-panel-group {{ |
| 43 | + display: block; |
| 44 | + overflow: visible; |
| 45 | + width: max-content; |
| 46 | + font-family: monaco, monospace; |
| 47 | + }} |
| 48 | + .iris-panel-body {{ |
| 49 | + padding-top: 0px; |
| 50 | + }} |
| 51 | + .iris-panel-title {{ |
| 52 | + padding-left: 3em; |
| 53 | + }} |
| 54 | + .iris-panel-title {{ |
| 55 | + margin-top: 7px; |
| 56 | + }} |
| 57 | +</style> |
| 58 | +<div class="panel-group iris-panel-group"> |
| 59 | + <div class="panel panel-default"> |
| 60 | + <div class="panel-heading"> |
| 61 | + <h4 class="panel-title"> |
| 62 | + <a class="iris" data-toggle="collapse" href="#collapse1-{obj_id}"> |
| 63 | +{summary} |
| 64 | + </a> |
| 65 | + </h4> |
| 66 | + </div> |
| 67 | + <div id="collapse1-{obj_id}" class="panel-collapse collapse in"> |
| 68 | + {content} |
| 69 | + </div> |
| 70 | + </div> |
| 71 | +</div> |
| 72 | + """ |
| 73 | + |
| 74 | + # Need to format the keywords: |
| 75 | + # `emt_id`, `obj_id`, `str_heading`, `opened`, `content`. |
| 76 | + _insert_content = """ |
| 77 | + <div class="panel-body iris-panel-body"> |
| 78 | + <h4 class="panel-title iris-panel-title"> |
| 79 | + <a class="iris" data-toggle="collapse" href="#{emt_id}-{obj_id}"> |
| 80 | +{str_heading} |
| 81 | + </a> |
| 82 | + </h4> |
| 83 | + </div> |
| 84 | + <div id="{emt_id}-{obj_id}" class="panel-collapse collapse{opened}"> |
| 85 | + <div class="panel-body iris-panel-body"> |
| 86 | + <p class="iris">{content}</p> |
| 87 | + </div> |
| 88 | + </div> |
| 89 | + """ |
| 90 | + |
| 91 | + def __init__(self, cube): |
| 92 | + """ |
| 93 | + Produce different representations of a :class:`~iris.cube.Cube`. |
| 94 | +
|
| 95 | + Args: |
| 96 | +
|
| 97 | + * cube |
| 98 | + the cube to produce representations of. |
| 99 | +
|
| 100 | + """ |
| 101 | + |
| 102 | + self.cube = cube |
| 103 | + self.cube_id = id(self.cube) |
| 104 | + self.cube_str = str(self.cube) |
| 105 | + |
| 106 | + self.summary = None |
| 107 | + self.str_headings = { |
| 108 | + 'Dimension coordinates:': None, |
| 109 | + 'Auxiliary coordinates:': None, |
| 110 | + 'Derived coordinates:': None, |
| 111 | + 'Scalar coordinates:': None, |
| 112 | + 'Attributes:': None, |
| 113 | + 'Cell methods:': None, |
| 114 | + } |
| 115 | + self.major_headings = ['Dimension coordinates:', |
| 116 | + 'Auxiliary coordinates:', |
| 117 | + 'Attributes:'] |
| 118 | + |
| 119 | + def _get_bits(self): |
| 120 | + """ |
| 121 | + Parse the str representation of the cube to retrieve the elements |
| 122 | + to add to an html representation of the cube. |
| 123 | +
|
| 124 | + """ |
| 125 | + bits = self.cube_str.split('\n') |
| 126 | + self.summary = bits[0] |
| 127 | + left_indent = bits[1].split('D')[0] |
| 128 | + |
| 129 | + # Get heading indices within the printout. |
| 130 | + start_inds = [] |
| 131 | + for hdg in self.str_headings.keys(): |
| 132 | + heading = '{}{}'.format(left_indent, hdg) |
| 133 | + try: |
| 134 | + start_ind = bits.index(heading) |
| 135 | + except ValueError: |
| 136 | + continue |
| 137 | + else: |
| 138 | + start_inds.append(start_ind) |
| 139 | + # Make sure the indices are in order. |
| 140 | + start_inds = sorted(start_inds) |
| 141 | + # Mark the end of the file. |
| 142 | + start_inds.append(None) |
| 143 | + |
| 144 | + # Retrieve info for each heading from the printout. |
| 145 | + for i0, i1 in zip(start_inds[:-1], start_inds[1:]): |
| 146 | + str_heading_name = bits[i0].strip() |
| 147 | + if i1 is not None: |
| 148 | + content = bits[i0 + 1: i1] |
| 149 | + else: |
| 150 | + content = bits[i0 + 1:] |
| 151 | + self.str_headings[str_heading_name] = content |
| 152 | + |
| 153 | + def _make_content(self): |
| 154 | + elements = [] |
| 155 | + for k, v in self.str_headings.items(): |
| 156 | + if v is not None: |
| 157 | + html_id = k.split(' ')[0].lower().strip(':') |
| 158 | + content = '\n'.join(line for line in v) |
| 159 | + collapse = ' in' if k in self.major_headings else '' |
| 160 | + element = self._insert_content.format(emt_id=html_id, |
| 161 | + obj_id=self.cube_id, |
| 162 | + str_heading=k, |
| 163 | + opened=collapse, |
| 164 | + content=content) |
| 165 | + elements.append(element) |
| 166 | + return '\n'.join(element for element in elements) |
| 167 | + |
| 168 | + def repr_html(self): |
| 169 | + """Produce an html representation of a cube and return it.""" |
| 170 | + self._get_bits() |
| 171 | + summary = self.summary |
| 172 | + content = self._make_content() |
| 173 | + return self._template.format(summary=summary, |
| 174 | + content=content, |
| 175 | + obj_id=self.cube_id, |
| 176 | + ) |
0 commit comments