Add .datacubes()
This commit is contained in:
parent
ea07545dc0
commit
4bcb09180e
@ -6,6 +6,7 @@ Initial Python Implementation
|
|||||||
[x] Query with request
|
[x] Query with request
|
||||||
[x] Iteration over leaves
|
[x] Iteration over leaves
|
||||||
[x] Iteration over datacubes
|
[x] Iteration over datacubes
|
||||||
|
[x] Command line creation from fdb list --compact
|
||||||
[ ] Set up periodic updates to climate-dt/extremes-dt again
|
[ ] Set up periodic updates to climate-dt/extremes-dt again
|
||||||
[ ] Maybe also do production db?
|
[ ] Maybe also do production db?
|
||||||
[ ] Do mars list to contraints conversion
|
[ ] Do mars list to contraints conversion
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
### Command Line Usage
|
# Command Line Usage
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
fdb list class=rd,expver=0001,... | qubed --from=fdblist --to=text
|
fdb list class=rd,expver=0001,... | qubed --from=fdblist --to=text
|
||||||
@ -19,3 +19,9 @@ fdb list class=rd,expver=0001,... | qubed --from=fdblist --to=text
|
|||||||
* `constraints`
|
* `constraints`
|
||||||
|
|
||||||
use `--input` and `--output` to specify input and output files respectively.
|
use `--input` and `--output` to specify input and output files respectively.
|
||||||
|
|
||||||
|
|
||||||
|
There's some handy test data in the `tests/data` directory. For example:
|
||||||
|
```bash
|
||||||
|
gzip -dc tests/data/fdb_list_compact.gz| qubed --from=fdblist
|
||||||
|
```
|
@ -79,11 +79,7 @@ for i, identifier in enumerate(cq.leaves()):
|
|||||||
Iterate over the datacubes:
|
Iterate over the datacubes:
|
||||||
|
|
||||||
```{code-cell} python3
|
```{code-cell} python3
|
||||||
for i, datacube in enumerate(cq.datacubes()):
|
cq.datacubes()
|
||||||
print(datacube)
|
|
||||||
if i > 10:
|
|
||||||
print("...")
|
|
||||||
break
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### A Real World Example
|
### A Real World Example
|
||||||
|
@ -43,6 +43,10 @@ class Qube:
|
|||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def root_node(cls, children: Iterable["Qube"]) -> 'Qube':
|
||||||
|
return cls.make("root", QEnum(("root",)), children)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_datacube(cls, datacube: dict[str, str | Sequence[str]]) -> 'Qube':
|
def from_datacube(cls, datacube: dict[str, str | Sequence[str]]) -> 'Qube':
|
||||||
key_vals = list(datacube.items())[::-1]
|
key_vals = list(datacube.items())[::-1]
|
||||||
@ -53,7 +57,7 @@ class Qube:
|
|||||||
values = [values]
|
values = [values]
|
||||||
children = [cls.make(key, QEnum(values), children)]
|
children = [cls.make(key, QEnum(values), children)]
|
||||||
|
|
||||||
return cls.make("root", QEnum(("root",)), children)
|
return cls.root_node(children)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -77,13 +81,11 @@ class Qube:
|
|||||||
children=from_dict(children)
|
children=from_dict(children)
|
||||||
) for k, children in d.items()]
|
) for k, children in d.items()]
|
||||||
|
|
||||||
return Qube.make(key = "root",
|
return Qube.root_node(from_dict(d))
|
||||||
values=QEnum(("root",)),
|
|
||||||
children = from_dict(d))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def empty(cls) -> 'Qube':
|
def empty(cls) -> 'Qube':
|
||||||
return cls.make("root", QEnum(("root",)), [])
|
return Qube.root_node([])
|
||||||
|
|
||||||
|
|
||||||
def __str__(self, depth = None, name = None) -> str:
|
def __str__(self, depth = None, name = None) -> str:
|
||||||
@ -93,8 +95,9 @@ class Qube:
|
|||||||
def print(self, depth = None, name: str | None = None):
|
def print(self, depth = None, name: str | None = None):
|
||||||
print(self.__str__(depth = depth, name = name))
|
print(self.__str__(depth = depth, name = name))
|
||||||
|
|
||||||
def html(self, depth = 2, collapse = True) -> HTML:
|
def html(self, depth = 2, collapse = True, name: str | None = None) -> HTML:
|
||||||
return HTML(node_tree_to_html(self, depth = depth, collapse = collapse))
|
node = dataclasses.replace(self, data = RootNodeData(key = name, values=self.values, metadata=self.metadata)) if name is not None else self
|
||||||
|
return HTML(node_tree_to_html(node=node, depth = depth, collapse = collapse))
|
||||||
|
|
||||||
def _repr_html_(self) -> str:
|
def _repr_html_(self) -> str:
|
||||||
return node_tree_to_html(self, depth = 2, collapse = True)
|
return node_tree_to_html(self, depth = 2, collapse = True)
|
||||||
@ -122,11 +125,18 @@ class Qube:
|
|||||||
else:
|
else:
|
||||||
yield leaf
|
yield leaf
|
||||||
|
|
||||||
def datacubes(self):
|
def datacubes(self) -> "Qube":
|
||||||
def to_list_of_cubes(node: Qube) -> list[list[Qube]]:
|
def to_list_of_cubes(node: Qube) -> Iterable[Qube]:
|
||||||
return [[node] + sub_cube for c in node.children for sub_cube in to_list_of_cubes(c)]
|
if not node.children:
|
||||||
|
yield node
|
||||||
|
# print(node.key)
|
||||||
|
for c in node.children:
|
||||||
|
# print(c)
|
||||||
|
for sub_cube in to_list_of_cubes(c):
|
||||||
|
yield dataclasses.replace(node, children=[sub_cube])
|
||||||
|
|
||||||
return to_list_of_cubes(self)
|
|
||||||
|
return Qube.root_node((q for c in self.children for q in to_list_of_cubes(c)))
|
||||||
|
|
||||||
def __getitem__(self, args) -> 'Qube':
|
def __getitem__(self, args) -> 'Qube':
|
||||||
key, value = args
|
key, value = args
|
||||||
@ -144,6 +154,7 @@ class Qube:
|
|||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def n_nodes(self) -> int:
|
def n_nodes(self) -> int:
|
||||||
|
if self.key == "root" and not self.children: return 0
|
||||||
return 1 + sum(c.n_nodes for c in self.children)
|
return 1 + sum(c.n_nodes for c in self.children)
|
||||||
|
|
||||||
def transform(self, func: 'Callable[[Qube], Qube | list[Qube]]') -> 'Qube':
|
def transform(self, func: 'Callable[[Qube], Qube | list[Qube]]') -> 'Qube':
|
||||||
|
@ -8,7 +8,7 @@ class TreeLike(Protocol):
|
|||||||
@property
|
@property
|
||||||
def children(self) -> Sequence["TreeLike"]: ... # Supports indexing like node.children[i]
|
def children(self) -> Sequence["TreeLike"]: ... # Supports indexing like node.children[i]
|
||||||
|
|
||||||
def summary(self, **kwargs) -> str: ...
|
def summary(self) -> str: ...
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class HTML():
|
class HTML():
|
||||||
|
@ -26,6 +26,12 @@ def test_n_leaves():
|
|||||||
# Size is 3*3*3 + 1*1*1 = 27 + 1
|
# Size is 3*3*3 + 1*1*1 = 27 + 1
|
||||||
assert q.n_leaves == 27 + 1
|
assert q.n_leaves == 27 + 1
|
||||||
|
|
||||||
|
def test_n_leaves_empty():
|
||||||
|
assert Qube.empty().n_leaves == 0
|
||||||
|
|
||||||
|
def test_n_nodes_empty():
|
||||||
|
assert Qube.empty().n_nodes == 0
|
||||||
|
|
||||||
|
|
||||||
def test_union():
|
def test_union():
|
||||||
q = Qube.from_dict({"a=1/2/3" : {"b=1" : {}},})
|
q = Qube.from_dict({"a=1/2/3" : {"b=1" : {}},})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user