Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
7ff26e7
Templates and TemplateRegistry
dmitriyrepin Jul 17, 2025
5ae7258
Merge remote-tracking branch 'upstream/v1' into v1
dmitriyrepin Jul 17, 2025
e8b95dc
Fix pre-commit issues
dmitriyrepin Jul 17, 2025
be772c7
Rever dev container changes
dmitriyrepin Jul 18, 2025
e43e4da
PR Review: address issues
dmitriyrepin Jul 18, 2025
80dd234
PR Review: register default templates at registry initialization
dmitriyrepin Jul 18, 2025
7caca55
Merge remote-tracking branch 'upstream/v1' into v1
dmitriyrepin Jul 22, 2025
2b2acf2
Dockerfile.dev
dmitriyrepin Jul 22, 2025
73d827a
segy_to_mdio_v1
dmitriyrepin Jul 22, 2025
befeca0
Clean up
dmitriyrepin Jul 23, 2025
ec057e6
Prototype review notes
Jul 23, 2025
59d12e9
Add dev comment
Jul 23, 2025
2f3eabf
Add notes that will be deleted later
dmitriyrepin Jul 23, 2025
0477bed
segy_to_mdio_v1 pass 1
dmitriyrepin Jul 26, 2025
5f7b135
indexing_v1 and blocked_io_v1
dmitriyrepin Jul 26, 2025
d6a4a35
Remove DEV notes
dmitriyrepin Jul 26, 2025
0b4c29f
Clean up
dmitriyrepin Jul 26, 2025
340f78a
Document bug location
dmitriyrepin Jul 26, 2025
2c34d34
Work around IndexError
dmitriyrepin Jul 27, 2025
93c4b30
Clean temporary code
dmitriyrepin Jul 27, 2025
324879a
More clean up
dmitriyrepin Jul 27, 2025
5debcf9
Remove *_1 infrastructure files
dmitriyrepin Jul 28, 2025
7b96b29
Restore accidently removed dask.array
dmitriyrepin Jul 29, 2025
3115299
Created an issue reproducer
dmitriyrepin Jul 29, 2025
4b1ae8f
Make the required template properties public
dmitriyrepin Jul 29, 2025
21e9e04
Simplify type converter
dmitriyrepin Jul 30, 2025
c5f9a63
Improve templates
dmitriyrepin Jul 30, 2025
b73cc68
Move test_type_converter.py
dmitriyrepin Jul 30, 2025
55315aa
Move test_type_converter.py
dmitriyrepin Jul 30, 2025
3e64fba
Revert to use the original grid
dmitriyrepin Jul 30, 2025
1f4687f
Integrate segy_to_mdio_v1_customized, fix indexing
dmitriyrepin Jul 30, 2025
e39d8c6
Add dimension coordinates in tem,plates
dmitriyrepin Jul 30, 2025
972a05d
Write statistics to Zarr
dmitriyrepin Jul 30, 2025
84ceb57
Delete factory_v1.py
dmitriyrepin Jul 30, 2025
4ff62bc
Complete integrationtest. Fix coordinates
dmitriyrepin Jul 31, 2025
543e886
Fir pre-commit errors
dmitriyrepin Jul 31, 2025
8017d98
PR review: fix trace_worker docstring
dmitriyrepin Aug 1, 2025
90754d3
Review: address some of the issue
dmitriyrepin Aug 1, 2025
f0a1c28
Fix bug
dmitriyrepin Aug 1, 2025
5d07ea4
dding todo for sum squares calculation
tasansal Aug 1, 2025
b503069
Refactor ChunkIterator
dmitriyrepin Aug 1, 2025
15febc9
Merge branch 'segy_to_mdio_v1'
dmitriyrepin Aug 2, 2025
5980ec9
Refactor ChunkIterator into ChunkIteratorV1
dmitriyrepin Aug 2, 2025
8e5f7a0
Remove segy_to_mdio_v1_customized, dataset_serializer.to_zarr
dmitriyrepin Aug 2, 2025
f0f42f3
Add support for trace headers without using _FillValue
dmitriyrepin Aug 4, 2025
a441db8
Use StorageLocation in trace_worker_v1
dmitriyrepin Aug 4, 2025
d574a47
Fix statistics attribute name
dmitriyrepin Aug 4, 2025
cf90b7e
PR review changes
dmitriyrepin Aug 4, 2025
a5ae874
PR Improvements: do a single write
dmitriyrepin Aug 4, 2025
ab08ef4
TODO: chunked write for non-dimensional coordinates and trace_mask
dmitriyrepin Aug 4, 2025
b970d74
Update StorageLocation to use fsspec
dmitriyrepin Aug 4, 2025
2f37c19
Reformat with pre-commit
dmitriyrepin Aug 4, 2025
4f30d95
Use domain name in get_grid_plan
dmitriyrepin Aug 4, 2025
71dcd0d
Fix non-dim coords and chunk_samples=False
dmitriyrepin Aug 5, 2025
1771491
Convert test_3d_import_v1 to V1
dmitriyrepin Aug 5, 2025
1f820a4
Merge-in latest 'upstream v1'
dmitriyrepin Aug 6, 2025
b52f534
Fix test_meta_dataset_read
dmitriyrepin Aug 6, 2025
7c6a38f
Merge branch 'v1' into segy_to_mdio_v1
tasansal Aug 7, 2025
ba3307f
remove whitespace
tasansal Aug 7, 2025
5e8a1c5
clean up comments
tasansal Aug 7, 2025
d03e460
update deps in lockfile
tasansal Aug 7, 2025
c8f7cff
simplify dim and non-dim coordinate handling after scan
tasansal Aug 7, 2025
047ea45
remove compatibility tests
tasansal Aug 8, 2025
08c1e70
add filtering capability to header worker
tasansal Aug 8, 2025
81af582
accept subset filter to pass to workers
tasansal Aug 8, 2025
f2d59a9
make v1 grid planner awesome
tasansal Aug 8, 2025
18726ed
double to single underscores in test names
tasansal Aug 8, 2025
75a0915
fix broken test harnesses due to incorrect Sequence import
tasansal Aug 8, 2025
174c8fd
clean up dev comment
tasansal Aug 8, 2025
63737a6
clean up whitespace
tasansal Aug 8, 2025
c55c080
use new module name
tasansal Aug 8, 2025
406a6b3
clean up segy_to_mdio_v1
tasansal Aug 8, 2025
73073e7
fix whitespace and remove unnecessary list call
tasansal Aug 8, 2025
29bbb70
these are defined as float64 in template
tasansal Aug 8, 2025
b13a57c
fix missing dimension coordinate for vertical axis
tasansal Aug 8, 2025
4d1dc8f
fix incorrect dtype comparison for time variable
tasansal Aug 8, 2025
0d410d3
simplify and fix critical bugs
tasansal Aug 8, 2025
e7ceced
rename v1 out of things and get rid of old code
tasansal Aug 8, 2025
fafe8ab
remove fixed todo
tasansal Aug 8, 2025
2b98486
remove more v1 from names
tasansal Aug 8, 2025
0517a57
rename chunk iterator
tasansal Aug 8, 2025
eb8bac7
fix dimensionality in tests due to new (missing) vertical dimension c…
tasansal Aug 8, 2025
22c4613
add todo for numpy ingestion
tasansal Aug 8, 2025
19812e9
fix references to non-v1 naming
tasansal Aug 8, 2025
00ef757
extract grid operations to its own function
tasansal Aug 8, 2025
528acb1
fix typo
tasansal Aug 8, 2025
d7b9013
add todo for simplifying storage location
tasansal Aug 8, 2025
792286c
Remove no_fill_var_names, add domain var to Seismic3DPreStackShotTemp…
dmitriyrepin Aug 8, 2025
c31bc45
Part 2 of the previous commit
dmitriyrepin Aug 8, 2025
bdde865
pre-commit formatting
dmitriyrepin Aug 8, 2025
e1405ec
remove dev mount
tasansal Aug 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
PR Review: register default templates at registry initialization
  • Loading branch information
dmitriyrepin committed Jul 18, 2025
commit 80dd2344d3f61a3a3e9f0ebd79d5add4dbda7c9d
19 changes: 13 additions & 6 deletions docs/template_registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,17 @@ The `TemplateRegistry` implements the singleton pattern to ensure there's only o

- **Singleton Pattern**: Ensures only one registry instance exists
- **Thread Safety**: All operations are thread-safe using locks
- **Case Insensitive**: Template names are normalized to lowercase
- **Global Access**: Convenient global functions for common operations
- **Advanced Support**: Reset functionality for environment re-usability.
- **Default Templates**: The registry is instantiated with the default set of templates:
- PostStack2DTime
- PostStack3DTime
- PreStackCdpGathers3DTime
- PreStackShotGathers3DTime
- PostStack2DDepth
- PostStack3DDepth
- PreStackCdpGathers3DDepth
- PreStackShotGathers3DDepth

## Usage

Expand Down Expand Up @@ -94,7 +102,7 @@ Registers a template instance and returns its normalized name.

- **Parameters:**
- `instance`: Template instance implementing `AbstractDatasetTemplate`
- **Returns:** The normalized template name (lowercase)
- **Returns:** The template name
- **Raises:** `ValueError` if template name is already registered

#### `get(template_name: str) -> AbstractDatasetTemplate`
Expand Down Expand Up @@ -126,7 +134,7 @@ Checks if a template is registered.

Returns a list of all registered template names.

- **Returns:** List of template names (in lowercase)
- **Returns:** List of template names

#### `clear() -> None`

Expand Down Expand Up @@ -187,9 +195,8 @@ for thread in threads:

1. **Use Global Functions**: For simple operations, prefer the global convenience functions
2. **Register Early**: Register all templates during application startup
3. **Case Insensitive Names**: Template names are automatically normalized to lowercase
4. **Thread Safety**: The registry is thread-safe, but individual templates may not be
5. **Testing Isolation**: Always reset the singleton in test setup/teardown
3. **Thread Safety**: The registry is thread-safe, but individual templates may not be
4. **Testing Isolation**: Always reset the singleton in test setup/teardown

## Example: Complete Template Management

Expand Down
30 changes: 26 additions & 4 deletions src/mdio/schemas/v1/templates/template_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
from typing import Optional

from mdio.schemas.v1.templates.abstract_dataset_template import AbstractDatasetTemplate
from mdio.schemas.v1.templates.seismic_2d_poststack import Seismic2DPostStackTemplate
from mdio.schemas.v1.templates.seismic_3d_poststack import Seismic3DPostStackTemplate
from mdio.schemas.v1.templates.seismic_3d_prestack_cdp import Seismic3DPreStackCDPTemplate
from mdio.schemas.v1.templates.seismic_3d_prestack_shot import Seismic3DPreStackShotTemplate


class TemplateRegistry:
Expand Down Expand Up @@ -34,6 +38,7 @@ def __init__(self) -> None:
if not self._initialized:
self._templates: dict[str, AbstractDatasetTemplate] = {}
self._registry_lock = threading.RLock()
self._register_default_templates()
TemplateRegistry._initialized = True

def register(self, instance: AbstractDatasetTemplate) -> str:
Expand All @@ -49,13 +54,30 @@ def register(self, instance: AbstractDatasetTemplate) -> str:
ValueError: If the template name is already registered.
"""
with self._registry_lock:
name = instance.get_name().lower()
name = instance.get_name()
if name in self._templates:
err = f"Template '{name}' is already registered."
raise ValueError(err)
self._templates[name] = instance
return name

def _register_default_templates(self) -> None:
"""Register default templates if needed.

This method can be overridden by subclasses to register default templates.
"""
self.register(Seismic2DPostStackTemplate("time"))
self.register(Seismic2DPostStackTemplate("depth"))

self.register(Seismic3DPostStackTemplate("time"))
self.register(Seismic3DPostStackTemplate("depth"))

self.register(Seismic3DPreStackCDPTemplate("time"))
self.register(Seismic3DPreStackCDPTemplate("depth"))

self.register(Seismic3DPreStackShotTemplate("time"))
self.register(Seismic3DPreStackShotTemplate("depth"))

def get(self, template_name: str) -> AbstractDatasetTemplate:
"""Get a template from the registry by its name.

Expand All @@ -69,7 +91,7 @@ def get(self, template_name: str) -> AbstractDatasetTemplate:
KeyError: If the template is not registered.
"""
with self._registry_lock:
name = template_name.lower()
name = template_name
if name not in self._templates:
err = f"Template '{name}' is not registered."
raise KeyError(err)
Expand All @@ -85,7 +107,7 @@ def unregister(self, template_name: str) -> None:
KeyError: If the template is not registered.
"""
with self._registry_lock:
name = template_name.lower()
name = template_name
if name not in self._templates:
err_msg = f"Template '{name}' is not registered."
raise KeyError(err_msg)
Expand All @@ -101,7 +123,7 @@ def is_registered(self, template_name: str) -> bool:
True if the template is registered, False otherwise.
"""
with self._registry_lock:
name = template_name.lower()
name = template_name
return name in self._templates

def list_all_templates(self) -> list[str]:
Expand Down
97 changes: 61 additions & 36 deletions tests/unit/v1/templates/test_template_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,34 +146,22 @@ def test_unregister_nonexistent_template(self) -> None:
with pytest.raises(KeyError, match="Template 'nonexistent' is not registered"):
registry.unregister("nonexistent")

def test_case_insensitive_operations(self) -> None:
"""Test that all operations are case-insensitive."""
registry = TemplateRegistry()
template = MockDatasetTemplate("Test_Template")

# Register template
registry.register(template)

# All these should work (case insensitive)
assert registry.is_registered("test_template")
assert registry.is_registered("TEST_TEMPLATE")
assert registry.is_registered("Test_Template")

# Get with different cases
assert registry.get("test_template") is template
assert registry.get("TEST_TEMPLATE") is template
assert registry.get("Test_Template") is template

# Unregister with different case
registry.unregister("TEST_TEMPLATE")
assert not registry.is_registered("test_template")

def test_list_all_templates(self) -> None:
"""Test listing all registered templates."""
registry = TemplateRegistry()

# Initially empty
assert registry.list_all_templates() == []
# Default templates are always installed
templates = list_templates()
assert len(templates) == 8
assert "PostStack2DTime" in templates
assert "PostStack3DTime" in templates
assert "PreStackCdpGathers3DTime" in templates
assert "PreStackShotGathers3DTime" in templates

assert "PostStack2DDepth" in templates
assert "PostStack3DDepth" in templates
assert "PreStackCdpGathers3DDepth" in templates
assert "PreStackShotGathers3DDepth" in templates

# Add some templates
template1 = MockDatasetTemplate("Template_One")
Expand All @@ -183,29 +171,42 @@ def test_list_all_templates(self) -> None:
registry.register(template2)

templates = registry.list_all_templates()
assert len(templates) == 2
assert "template_one" in templates
assert "template_two" in templates
assert len(templates) == 10
assert "Template_One" in templates
assert "Template_Two" in templates

def test_clear_templates(self) -> None:
"""Test clearing all templates."""
registry = TemplateRegistry()

# Default templates are always installed
templates = list_templates()
assert len(templates) == 8

# Add some templates
template1 = MockDatasetTemplate("template1")
template2 = MockDatasetTemplate("template2")
template1 = MockDatasetTemplate("Template1")
template2 = MockDatasetTemplate("Template2")

registry.register(template1)
registry.register(template2)

assert len(registry.list_all_templates()) == 2
assert len(registry.list_all_templates()) == 10

# Clear all
registry.clear()

assert len(registry.list_all_templates()) == 0
assert not registry.is_registered("template1")
assert not registry.is_registered("template2")
assert not registry.is_registered("Template1")
assert not registry.is_registered("Template2")
# default templates are also cleared
assert not registry.is_registered("PostStack2DTime")
assert not registry.is_registered("PostStack3DTime")
assert not registry.is_registered("PreStackCdpGathers3DTime")
assert not registry.is_registered("PreStackShotGathers3DTime")
assert not registry.is_registered("PostStack2DDepth")
assert not registry.is_registered("PostStack3DDepth")
assert not registry.is_registered("PreStackCdpGathers3DDepth")
assert not registry.is_registered("PreStackShotGathers3DDepth")

def test_reset_instance(self) -> None:
"""Test resetting the singleton instance."""
Expand All @@ -216,12 +217,22 @@ def test_reset_instance(self) -> None:
# Reset the instance
TemplateRegistry._reset_instance()

# New instance should be different and empty
# New instance should be different and contain default templates only
registry2 = TemplateRegistry()

assert registry1 is not registry2
assert not registry2.is_registered("test")
assert len(registry2.list_all_templates()) == 0

# default templates are registered
assert len(registry2.list_all_templates()) == 8
assert registry2.is_registered("PostStack2DTime")
assert registry2.is_registered("PostStack3DTime")
assert registry2.is_registered("PreStackCdpGathers3DTime")
assert registry2.is_registered("PreStackShotGathers3DTime")
assert registry2.is_registered("PostStack2DDepth")
assert registry2.is_registered("PostStack3DDepth")
assert registry2.is_registered("PreStackCdpGathers3DDepth")
assert registry2.is_registered("PreStackShotGathers3DDepth")


class TestGlobalFunctions:
Expand Down Expand Up @@ -258,14 +269,27 @@ def test_register_template_global(self) -> None:

def test_list_templates_global(self) -> None:
"""Test global template listing."""
# Default templates are always installed
templates = list_templates()
assert len(templates) == 8
assert "PostStack2DTime" in templates
assert "PostStack3DTime" in templates
assert "PreStackCdpGathers3DTime" in templates
assert "PreStackShotGathers3DTime" in templates

assert "PostStack2DDepth" in templates
assert "PostStack3DDepth" in templates
assert "PreStackCdpGathers3DDepth" in templates
assert "PreStackShotGathers3DDepth" in templates

template1 = MockDatasetTemplate("template1")
template2 = MockDatasetTemplate("template2")

register_template(template1)
register_template(template2)

templates = list_templates()
assert len(templates) == 2
assert len(templates) == 10
assert "template1" in templates
assert "template2" in templates

Expand Down Expand Up @@ -310,7 +334,8 @@ def register_template_worker(template_id: int) -> None:
# All registrations should succeed
assert len(errors) == 0
assert len(results) == 10
assert len(registry.list_all_templates()) == 10
# Including 8 default templates
assert len(registry.list_all_templates()) == 18

# Check all templates are registered
for i in range(10):
Expand Down
Loading