Skip to content

Commit d82dd28

Browse files
committed
Add html representations for key classes
1 parent 6e9616d commit d82dd28

File tree

3 files changed

+201
-0
lines changed

3 files changed

+201
-0
lines changed

src/mdio/builder/dataset_builder.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,3 +318,84 @@ def __repr__(self) -> str:
318318
f"coordinates={coord_names}, "
319319
f"variables={var_names})"
320320
)
321+
322+
def _repr_html_(self) -> str:
323+
"""Return an HTML representation of the builder for Jupyter notebooks."""
324+
dim_rows = ""
325+
for dim in self._dimensions:
326+
dim_rows += f"<tr><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{dim.name}</td><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{dim.size}</td></tr>"
327+
328+
coord_rows = ""
329+
for coord in self._coordinates:
330+
dims_str = ", ".join(d.name for d in coord.dimensions)
331+
coord_rows += f"<tr><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{coord.name}</td><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{dims_str}</td><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{coord.data_type}</td></tr>"
332+
333+
var_rows = ""
334+
for var in self._variables:
335+
dims_str = ", ".join(d.name for d in var.dimensions)
336+
var_rows += f"<tr><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{var.name}</td><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{dims_str}</td><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{var.data_type}</td></tr>"
337+
338+
html = f"""
339+
<div style="font-family: monospace; border: 1px solid rgba(128, 128, 128, 0.3); border-radius: 5px; padding: 15px; max-width: 1000px;">
340+
<div style="padding: 10px; margin: -15px -15px 15px -15px; border-bottom: 2px solid rgba(128, 128, 128, 0.3);">
341+
<strong style="font-size: 1.1em;">MDIODatasetBuilder</strong>
342+
</div>
343+
<div style="margin-bottom: 15px;">
344+
<strong>Name:</strong> {self._metadata.name}<br>
345+
<strong>State:</strong> {self._state.name}<br>
346+
<strong>API Version:</strong> {self._metadata.api_version}<br>
347+
<strong>Created:</strong> {self._metadata.created_on.strftime('%Y-%m-%d %H:%M:%S UTC')}
348+
</div>
349+
<details open>
350+
<summary style="cursor: pointer; font-weight: bold; margin-bottom: 8px;">▸ Dimensions ({len(self._dimensions)})</summary>
351+
<div style="margin-left: 20px;">
352+
<table style="width: 100%; border-collapse: collapse;">
353+
<thead>
354+
<tr style="border-bottom: 2px solid rgba(128, 128, 128, 0.4);">
355+
<th style="text-align: left; padding: 8px; font-weight: 600;">Name</th>
356+
<th style="text-align: left; padding: 8px; font-weight: 600;">Size</th>
357+
</tr>
358+
</thead>
359+
<tbody>
360+
{dim_rows if dim_rows else '<tr><td colspan="2" style="padding: 8px; opacity: 0.5; text-align: left;">No dimensions added</td></tr>'}
361+
</tbody>
362+
</table>
363+
</div>
364+
</details>
365+
<details open>
366+
<summary style="cursor: pointer; font-weight: bold; margin: 15px 0 8px 0;">▸ Coordinates ({len(self._coordinates)})</summary>
367+
<div style="margin-left: 20px;">
368+
<table style="width: 100%; border-collapse: collapse;">
369+
<thead>
370+
<tr style="border-bottom: 2px solid rgba(128, 128, 128, 0.4);">
371+
<th style="text-align: left; padding: 8px; font-weight: 600;">Name</th>
372+
<th style="text-align: left; padding: 8px; font-weight: 600;">Dimensions</th>
373+
<th style="text-align: left; padding: 8px; font-weight: 600;">Type</th>
374+
</tr>
375+
</thead>
376+
<tbody>
377+
{coord_rows if coord_rows else '<tr><td colspan="3" style="padding: 8px; opacity: 0.5; text-align: left;">No coordinates added</td></tr>'}
378+
</tbody>
379+
</table>
380+
</div>
381+
</details>
382+
<details open>
383+
<summary style="cursor: pointer; font-weight: bold; margin: 15px 0 8px 0;">▸ Variables ({len(self._variables)})</summary>
384+
<div style="margin-left: 20px;">
385+
<table style="width: 100%; border-collapse: collapse;">
386+
<thead>
387+
<tr style="border-bottom: 2px solid rgba(128, 128, 128, 0.4);">
388+
<th style="text-align: left; padding: 8px; font-weight: 600;">Name</th>
389+
<th style="text-align: left; padding: 8px; font-weight: 600;">Dimensions</th>
390+
<th style="text-align: left; padding: 8px; font-weight: 600;">Type</th>
391+
</tr>
392+
</thead>
393+
<tbody>
394+
{var_rows if var_rows else '<tr><td colspan="3" style="padding: 8px; opacity: 0.5; text-align: left;">No variables added</td></tr>'}
395+
</tbody>
396+
</table>
397+
</div>
398+
</details>
399+
</div>
400+
"""
401+
return html

src/mdio/builder/template_registry.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,37 @@ def __repr__(self) -> str:
171171
template_names = sorted(self._templates.keys())
172172
return f"TemplateRegistry(templates={template_names})"
173173

174+
def _repr_html_(self) -> str:
175+
"""Return an HTML representation of the registry for Jupyter notebooks."""
176+
template_rows = ""
177+
for name in sorted(self._templates.keys()):
178+
template = self._templates[name]
179+
template_class = template.__class__.__name__
180+
data_domain = getattr(template, '_data_domain', '—')
181+
template_rows += f"<tr><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{name}</td><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{template_class}</td><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{data_domain}</td></tr>"
182+
183+
html = f"""
184+
<div style="font-family: monospace; border: 1px solid rgba(128, 128, 128, 0.3); border-radius: 5px; padding: 15px; max-width: 1000px;">
185+
<div style="padding: 10px; margin: -15px -15px 15px -15px; border-bottom: 2px solid rgba(128, 128, 128, 0.3);">
186+
<strong style="font-size: 1.1em;">TemplateRegistry</strong>
187+
<span style="margin-left: 15px; opacity: 0.7;">({len(self._templates)} templates)</span>
188+
</div>
189+
<table style="width: 100%; border-collapse: collapse;">
190+
<thead>
191+
<tr style="border-bottom: 2px solid rgba(128, 128, 128, 0.4);">
192+
<th style="text-align: left; padding: 10px; font-weight: 600;">Template Name</th>
193+
<th style="text-align: left; padding: 10px; font-weight: 600;">Class</th>
194+
<th style="text-align: left; padding: 10px; font-weight: 600;">Domain</th>
195+
</tr>
196+
</thead>
197+
<tbody>
198+
{template_rows if template_rows else '<tr><td colspan="3" style="padding: 10px; opacity: 0.5; text-align: center;">No templates registered</td></tr>'}
199+
</tbody>
200+
</table>
201+
</div>
202+
"""
203+
return html
204+
174205

175206
# Global convenience functions
176207
def get_template_registry() -> TemplateRegistry:

src/mdio/builder/templates/abstract_dataset_template.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,95 @@ def __repr__(self) -> str:
6262
f"units={self._units})"
6363
)
6464

65+
def _repr_html_(self) -> str:
66+
"""Return an HTML representation of the template for Jupyter notebooks."""
67+
# Format dimensions
68+
dim_rows = ""
69+
if self._dim_names:
70+
for i, name in enumerate(self._dim_names):
71+
size = self._dim_sizes[i] if i < len(self._dim_sizes) else "Not set"
72+
is_spatial = "✓" if name in self._spatial_dim_names else ""
73+
dim_rows += f"<tr><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{name}</td><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{size}</td><td style='padding: 8px; text-align: center; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{is_spatial}</td></tr>"
74+
75+
# Format coordinates
76+
coord_rows = ""
77+
all_coords = list(self._physical_coord_names) + list(self._logical_coord_names)
78+
for coord in all_coords:
79+
coord_type = "Physical" if coord in self._physical_coord_names else "Logical"
80+
unit = self._units.get(coord, None)
81+
unit_str = f"{unit.name}" if unit else "—"
82+
coord_rows += f"<tr><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{coord}</td><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{coord_type}</td><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{unit_str}</td></tr>"
83+
84+
# Format units
85+
unit_rows = ""
86+
for key, unit in self._units.items():
87+
unit_rows += f"<tr><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{key}</td><td style='padding: 8px; text-align: left; border-bottom: 1px solid rgba(128, 128, 128, 0.2);'>{unit.name}</td></tr>"
88+
89+
html = f"""
90+
<div style="font-family: monospace; border: 1px solid rgba(128, 128, 128, 0.3); border-radius: 5px; padding: 15px; max-width: 1000px;">
91+
<div style="padding: 10px; margin: -15px -15px 15px -15px; border-bottom: 2px solid rgba(128, 128, 128, 0.3);">
92+
<strong style="font-size: 1.1em;">{self.__class__.__name__}</strong>
93+
</div>
94+
<div style="margin-bottom: 15px;">
95+
<strong>Template Name:</strong> {self.name}<br>
96+
<strong>Data Domain:</strong> {self._data_domain}<br>
97+
<strong>Default Variable:</strong> {self._default_variable_name}<br>
98+
<strong>Chunk Shape:</strong> {self._var_chunk_shape if self._var_chunk_shape else 'Not set'}
99+
</div>
100+
<details open>
101+
<summary style="cursor: pointer; font-weight: bold; margin-bottom: 8px;">▸ Dimensions ({len(self._dim_names)})</summary>
102+
<div style="margin-left: 20px;">
103+
<table style="width: 100%; border-collapse: collapse;">
104+
<thead>
105+
<tr style="border-bottom: 2px solid rgba(128, 128, 128, 0.4);">
106+
<th style="text-align: left; padding: 8px; font-weight: 600;">Name</th>
107+
<th style="text-align: left; padding: 8px; font-weight: 600;">Size</th>
108+
<th style="text-align: center; padding: 8px; font-weight: 600;">Spatial</th>
109+
</tr>
110+
</thead>
111+
<tbody>
112+
{dim_rows if dim_rows else '<tr><td colspan="3" style="padding: 8px; opacity: 0.5; text-align: left;">No dimensions defined</td></tr>'}
113+
</tbody>
114+
</table>
115+
</div>
116+
</details>
117+
<details open>
118+
<summary style="cursor: pointer; font-weight: bold; margin: 15px 0 8px 0;">▸ Coordinates ({len(all_coords)})</summary>
119+
<div style="margin-left: 20px;">
120+
<table style="width: 100%; border-collapse: collapse;">
121+
<thead>
122+
<tr style="border-bottom: 2px solid rgba(128, 128, 128, 0.4);">
123+
<th style="text-align: left; padding: 8px; font-weight: 600;">Name</th>
124+
<th style="text-align: left; padding: 8px; font-weight: 600;">Type</th>
125+
<th style="text-align: left; padding: 8px; font-weight: 600;">Units</th>
126+
</tr>
127+
</thead>
128+
<tbody>
129+
{coord_rows if coord_rows else '<tr><td colspan="3" style="padding: 8px; opacity: 0.5; text-align: left;">No coordinates defined</td></tr>'}
130+
</tbody>
131+
</table>
132+
</div>
133+
</details>
134+
<details>
135+
<summary style="cursor: pointer; font-weight: bold; margin: 15px 0 8px 0;">▸ Units ({len(self._units)})</summary>
136+
<div style="margin-left: 20px;">
137+
<table style="width: 100%; border-collapse: collapse;">
138+
<thead>
139+
<tr style="border-bottom: 2px solid rgba(128, 128, 128, 0.4);">
140+
<th style="text-align: left; padding: 8px; font-weight: 600;">Key</th>
141+
<th style="text-align: left; padding: 8px; font-weight: 600;">Unit</th>
142+
</tr>
143+
</thead>
144+
<tbody>
145+
{unit_rows if unit_rows else '<tr><td colspan="2" style="padding: 8px; opacity: 0.5; text-align: left;">No units defined</td></tr>'}
146+
</tbody>
147+
</table>
148+
</div>
149+
</details>
150+
</div>
151+
"""
152+
return html
153+
65154
def build_dataset(
66155
self,
67156
name: str,

0 commit comments

Comments
 (0)