11from __future__ import annotations
22
33import os .path as osp
4+ import re
45import time
56import warnings
7+ from pathlib import Path
68from typing import TYPE_CHECKING , Sequence
79
810import numpy as np
11+ from attrs import define
912from pyquaternion import Quaternion
1013
1114from t4_devkit .common .geometry import is_box_in_image
3841 Visibility ,
3942 )
4043
41- __all__ = ("Tier4" ,)
44+ __all__ = ["DBMetadata" , "load_metadata" , "Tier4" ]
45+
46+
47+ @define
48+ class DBMetadata :
49+ data_root : str
50+ dataset_id : str
51+ version : str | None
52+
53+
54+ def load_metadata (db_root : str ) -> DBMetadata :
55+ """Load metadata of T4 dataset including root directory path, dataset ID, and version.
56+
57+ Args:
58+ db_root (str): Path to root directory of database.
59+
60+ Returns:
61+ Metadata of T4 dataset.
62+ """
63+ db_root_path = Path (db_root )
64+
65+ version_pattern = re .compile (r".*/\d+$" )
66+ versions = [d .name for d in db_root_path .iterdir () if version_pattern .match (d .as_posix ())]
67+
68+ if versions :
69+ version = sorted (versions )[- 1 ]
70+ data_root = db_root_path .joinpath (version ).as_posix ()
71+ else :
72+ version = None
73+ data_root = db_root_path .as_posix ()
74+
75+ return DBMetadata (data_root = data_root , dataset_id = db_root_path .name , version = version )
4276
4377
4478class Tier4 :
4579 """Database class for T4 dataset to help query and retrieve information from the database."""
4680
47- def __init__ (self , version : str , data_root : str , verbose : bool = True ) -> None :
81+ schema_dir : str = "annotation"
82+
83+ def __init__ (self , data_root : str , verbose : bool = True ) -> None :
4884 """Load database and creates reverse indexes and shortcuts.
4985
5086 Args:
@@ -54,7 +90,7 @@ def __init__(self, version: str, data_root: str, verbose: bool = True) -> None:
5490
5591 Examples:
5692 >>> from t4_devkit import Tier4
57- >>> t4 = Tier4("annotation", " data/tier4")
93+ >>> t4 = Tier4("data/tier4")
5894 ======
5995 Loading T4 tables in `annotation`...
6096 Reverse indexing...
@@ -80,16 +116,14 @@ def __init__(self, version: str, data_root: str, verbose: bool = True) -> None:
80116 ======
81117
82118 """
83- self .version = version
84- self .data_root = data_root
85- self .verbose = verbose
119+ self ._metadata = load_metadata (data_root )
86120
87121 if not osp .exists (self .data_root ):
88122 raise FileNotFoundError (f"Database directory is not found: { self .data_root } " )
89123
90124 start_time = time .time ()
91125 if verbose :
92- print (f"======\n Loading T4 tables in `{ self .version } `..." )
126+ print (f"======\n Loading T4 tables in `{ self .schema_dir } `..." )
93127
94128 # assign tables explicitly
95129 self .attribute : list [Attribute ] = self .__load_table__ (SchemaName .ATTRIBUTE )
@@ -127,6 +161,21 @@ def __init__(self, version: str, data_root: str, verbose: bool = True) -> None:
127161 self ._timeseries_helper = TimeseriesHelper (self )
128162 self ._rendering_helper = RenderingHelper (self )
129163
164+ @property
165+ def data_root (self ) -> str :
166+ """Return the path to dataset root directory."""
167+ return self ._metadata .data_root
168+
169+ @property
170+ def dataset_id (self ) -> str :
171+ """Return the dataset ID."""
172+ return self ._metadata .dataset_id
173+
174+ @property
175+ def version (self ) -> str | None :
176+ """Return the dataset version, or None if it is failed to lookup."""
177+ return self ._metadata .version
178+
130179 def __load_table__ (self , schema : SchemaName ) -> list [SchemaTable ]:
131180 """Load schema table from a json file.
132181
@@ -139,7 +188,7 @@ def __load_table__(self, schema: SchemaName) -> list[SchemaTable]:
139188 Returns:
140189 Loaded table data saved in `.json`.
141190 """
142- filepath = osp .join (self .data_root , self .version , schema .filename )
191+ filepath = osp .join (self .data_root , self .schema_dir , schema .filename )
143192 if not osp .exists (filepath ) and schema .is_optional ():
144193 return []
145194
0 commit comments