fastremap 1.16.1__tar.gz → 1.17.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastremap-1.17.1/.github/workflows/lint.yml +35 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/.github/workflows/test.yml +1 -1
- fastremap-1.17.1/.vscode/settings.json +4 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/AUTHORS +1 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/ChangeLog +20 -0
- fastremap-1.17.1/MANIFEST.in +3 -0
- {fastremap-1.16.1/fastremap.egg-info → fastremap-1.17.1}/PKG-INFO +6 -5
- {fastremap-1.16.1 → fastremap-1.17.1}/README.md +3 -2
- {fastremap-1.16.1 → fastremap-1.17.1}/automated_test.py +81 -5
- fastremap-1.17.1/fastremap/__init__.py +49 -0
- fastremap-1.17.1/fastremap/fastremap.pyi +500 -0
- {fastremap-1.16.1/src → fastremap-1.17.1/fastremap}/fastremap.pyx +74 -56
- fastremap-1.17.1/fastremap/py.typed +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1/fastremap.egg-info}/PKG-INFO +6 -5
- {fastremap-1.16.1 → fastremap-1.17.1}/fastremap.egg-info/SOURCES.txt +11 -5
- fastremap-1.17.1/fastremap.egg-info/pbr.json +1 -0
- fastremap-1.17.1/mypy.allowlist +2 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/requirements_dev.txt +2 -1
- {fastremap-1.16.1 → fastremap-1.17.1}/setup.cfg +1 -2
- {fastremap-1.16.1 → fastremap-1.17.1}/setup.py +4 -3
- fastremap-1.16.1/MANIFEST.in +0 -3
- fastremap-1.16.1/fastremap.egg-info/pbr.json +0 -1
- {fastremap-1.16.1 → fastremap-1.17.1}/.dockerignore +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/.github/workflows/build_wheel.yml +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/LICENSE +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/build_linux.sh +0 -0
- {fastremap-1.16.1/src → fastremap-1.17.1/fastremap}/fastremap.pxd +0 -0
- {fastremap-1.16.1/src → fastremap-1.17.1/fastremap}/ipt.hpp +0 -0
- {fastremap-1.16.1/src → fastremap-1.17.1/fastremap}/ska_flat_hash_map.hpp +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/fastremap.egg-info/dependency_links.txt +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/fastremap.egg-info/not-zip-safe +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/fastremap.egg-info/requires.txt +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/fastremap.egg-info/top_level.txt +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/manylinux1.Dockerfile +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/manylinux2010.Dockerfile +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/manylinux2014.Dockerfile +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/pyproject.toml +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/requirements.txt +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/test.py +0 -0
- {fastremap-1.16.1 → fastremap-1.17.1}/tox.ini +0 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
name: Lint
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [master]
|
6
|
+
pull_request:
|
7
|
+
branches: [master]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
mypy:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
steps:
|
13
|
+
- name: Setup Python
|
14
|
+
uses: actions/setup-python@v4
|
15
|
+
with:
|
16
|
+
python-version: 3.9
|
17
|
+
architecture: x64
|
18
|
+
|
19
|
+
- name: Checkout
|
20
|
+
uses: actions/checkout@v3
|
21
|
+
|
22
|
+
- name: Install dependencies
|
23
|
+
run: pip install -r requirements.txt -r requirements_dev.txt
|
24
|
+
|
25
|
+
- name: Add mypy annotator
|
26
|
+
uses: pr-annotators/mypy-pr-annotator@v1.0.0
|
27
|
+
|
28
|
+
- name: Run mypy
|
29
|
+
run: mypy fastremap
|
30
|
+
|
31
|
+
- name: Compile
|
32
|
+
run: python setup.py develop
|
33
|
+
|
34
|
+
- name: Run stub tests
|
35
|
+
run: python -m mypy.stubtest fastremap --allowlist mypy.allowlist
|
@@ -15,7 +15,7 @@ jobs:
|
|
15
15
|
strategy:
|
16
16
|
matrix:
|
17
17
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
18
|
-
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
18
|
+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13.3"]
|
19
19
|
|
20
20
|
steps:
|
21
21
|
- name: Set up Python ${{ matrix.python-version }}
|
@@ -1,6 +1,26 @@
|
|
1
1
|
CHANGES
|
2
2
|
=======
|
3
3
|
|
4
|
+
1.17.1
|
5
|
+
------
|
6
|
+
|
7
|
+
* fixtest: promote fit\_dtype in testing
|
8
|
+
* fix: fit\_dtype is used externally
|
9
|
+
* docs: add collaborators
|
10
|
+
|
11
|
+
1.17.0
|
12
|
+
------
|
13
|
+
|
14
|
+
* Add typing support (#45)
|
15
|
+
* Add optional arguments to remap\_from\_array functions (#46)
|
16
|
+
|
17
|
+
1.16.2
|
18
|
+
------
|
19
|
+
|
20
|
+
* perf+fix: faster simple case return + fix inverse
|
21
|
+
* test: check for renumber misordering
|
22
|
+
* fix(unique): ensure output of unique\_via\_renumber is sorted
|
23
|
+
|
4
24
|
1.16.1
|
5
25
|
------
|
6
26
|
|
@@ -1,13 +1,12 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: fastremap
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.17.1
|
4
4
|
Summary: Remap, mask, renumber, unique, and in-place transposition of 3D labeled images. Point cloud too.
|
5
5
|
Home-page: https://github.com/seung-lab/fastremap/
|
6
6
|
Author: William Silversmith
|
7
7
|
Author-email: ws9@princeton.edu
|
8
8
|
Classifier: Intended Audience :: Developers
|
9
9
|
Classifier: Development Status :: 5 - Production/Stable
|
10
|
-
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
|
11
10
|
Classifier: Programming Language :: Python
|
12
11
|
Classifier: Programming Language :: Python :: 3
|
13
12
|
Classifier: Programming Language :: Python :: 3.7
|
@@ -27,6 +26,7 @@ Dynamic: classifier
|
|
27
26
|
Dynamic: description
|
28
27
|
Dynamic: description-content-type
|
29
28
|
Dynamic: home-page
|
29
|
+
Dynamic: license-file
|
30
30
|
Dynamic: requires-dist
|
31
31
|
Dynamic: requires-python
|
32
32
|
Dynamic: summary
|
@@ -94,8 +94,9 @@ binaries = fastremap.tobytes(labels, (64,64,64), order="F")
|
|
94
94
|
- **inverse_component_map**: Extract an int-to-list-of-ints dictionary mapping from an image containing groups of components to an image containing the components.
|
95
95
|
- **remap_from_array:** Same as remap, but the map is an array where the key is the array index and the value is the value.
|
96
96
|
- **remap_from_array_kv:** Same as remap, but the map consists of two equal sized arrays, the first containing keys, the second containing values.
|
97
|
-
- **
|
98
|
-
- **
|
97
|
+
- **transpose:** Perform an in-place matrix transposition for rectangular arrays if memory is contiguous, apply the stock `np.transpose` function otherwise.
|
98
|
+
- **asfortranarray:** Perform an in-place matrix transposition for rectangular arrays if memory is contiguous, apply the stock `np.asfortranarray` function otherwise.
|
99
|
+
- **ascontiguousarray:** Perform an in-place matrix transposition for rectangular arrays if memory is contiguous, apply the stock `np.ascontiguousarray` function otherwise.
|
99
100
|
- **minmax:** Compute the min and max of an array in one pass.
|
100
101
|
- **pixel_pairs:** Computes the number of adjacent matching memory locations in an image. A quick heuristic for understanding if the image statistics are roughly similar to a connectomics segmentation.
|
101
102
|
- **foreground:** Count the number of non-zero voxels rapidly.
|
@@ -61,8 +61,9 @@ binaries = fastremap.tobytes(labels, (64,64,64), order="F")
|
|
61
61
|
- **inverse_component_map**: Extract an int-to-list-of-ints dictionary mapping from an image containing groups of components to an image containing the components.
|
62
62
|
- **remap_from_array:** Same as remap, but the map is an array where the key is the array index and the value is the value.
|
63
63
|
- **remap_from_array_kv:** Same as remap, but the map consists of two equal sized arrays, the first containing keys, the second containing values.
|
64
|
-
- **
|
65
|
-
- **
|
64
|
+
- **transpose:** Perform an in-place matrix transposition for rectangular arrays if memory is contiguous, apply the stock `np.transpose` function otherwise.
|
65
|
+
- **asfortranarray:** Perform an in-place matrix transposition for rectangular arrays if memory is contiguous, apply the stock `np.asfortranarray` function otherwise.
|
66
|
+
- **ascontiguousarray:** Perform an in-place matrix transposition for rectangular arrays if memory is contiguous, apply the stock `np.ascontiguousarray` function otherwise.
|
66
67
|
- **minmax:** Compute the min and max of an array in one pass.
|
67
68
|
- **pixel_pairs:** Computes the number of adjacent matching memory locations in an image. A quick heuristic for understanding if the image statistics are roughly similar to a connectomics segmentation.
|
68
69
|
- **foreground:** Count the number of non-zero voxels rapidly.
|
@@ -440,7 +440,7 @@ def test_unique(order):
|
|
440
440
|
|
441
441
|
labels = reorder(np.random.randint(0, 500, size=(128,128,128)))
|
442
442
|
uniq_np, idx_np, inv_np, cts_np = np.unique(labels, return_counts=True, return_index=True, return_inverse=True)
|
443
|
-
uniq_fr, idx_fr, cts_fr, inv_fr = fastremap.
|
443
|
+
uniq_fr, idx_fr, cts_fr, inv_fr = fastremap.fastremap._unique_via_array(labels.flatten(), np.max(labels), return_index=True, return_inverse=True)
|
444
444
|
assert np.all(uniq_np == uniq_fr)
|
445
445
|
assert np.all(inv_np.flatten() == inv_fr)
|
446
446
|
assert np.all(cts_np == cts_fr)
|
@@ -457,7 +457,7 @@ def test_unique(order):
|
|
457
457
|
|
458
458
|
labels = reorder(np.random.randint(-500, 500, size=(128,128,128)))
|
459
459
|
uniq_np, idx_np, inv_np, cts_np = np.unique(labels, return_counts=True, return_index=True, return_inverse=True)
|
460
|
-
uniq_fr, idx_fr, cts_fr, inv_fr = fastremap.
|
460
|
+
uniq_fr, idx_fr, cts_fr, inv_fr = fastremap.fastremap._unique_via_shifted_array(labels.flatten(), return_index=True, return_inverse=True)
|
461
461
|
assert np.all(uniq_np == uniq_fr)
|
462
462
|
assert np.all(inv_np.flatten() == inv_fr)
|
463
463
|
assert np.all(cts_np == cts_fr)
|
@@ -475,7 +475,7 @@ def test_unique(order):
|
|
475
475
|
# array_unique + shift
|
476
476
|
labels = reorder(np.random.randint(128**3 - 500, 128**3 + 500, size=(128,128,128)))
|
477
477
|
uniq_np, idx_np, inv_np, cts_np = np.unique(labels, return_counts=True, return_index=True, return_inverse=True)
|
478
|
-
uniq_fr, idx_fr, cts_fr, inv_fr = fastremap.
|
478
|
+
uniq_fr, idx_fr, cts_fr, inv_fr = fastremap.fastremap._unique_via_shifted_array(labels.flatten(), return_index=True, return_inverse=True)
|
479
479
|
assert np.all(uniq_np == uniq_fr)
|
480
480
|
assert np.all(inv_np.flatten() == inv_fr)
|
481
481
|
assert np.all(cts_np == cts_fr)
|
@@ -494,7 +494,7 @@ def test_unique(order):
|
|
494
494
|
labels = reorder(np.random.randint(0, 1, size=(128,128,128)))
|
495
495
|
labels[0,0,0] = 128**3 + 10
|
496
496
|
uniq_np, idx_np, inv_np, cts_np = np.unique(labels, return_counts=True, return_index=True, return_inverse=True)
|
497
|
-
uniq_fr, idx_fr, cts_fr, inv_fr = fastremap.
|
497
|
+
uniq_fr, idx_fr, cts_fr, inv_fr = fastremap.fastremap._unique_via_renumber(labels.flatten(), return_index=True, return_inverse=True)
|
498
498
|
assert np.all(uniq_np == uniq_fr)
|
499
499
|
assert np.all(inv_np.flatten() == inv_fr)
|
500
500
|
assert np.all(cts_np == cts_fr)
|
@@ -511,7 +511,7 @@ def test_unique(order):
|
|
511
511
|
|
512
512
|
labels = reorder(np.random.randint(-1000, 128**3, size=(100,100,100)))
|
513
513
|
uniq_np, cts_np = np.unique(labels, return_counts=True)
|
514
|
-
uniq_fr, cts_fr = fastremap.
|
514
|
+
uniq_fr, cts_fr = fastremap.fastremap._unique_via_sort(labels.flatten())
|
515
515
|
assert np.all(uniq_np == uniq_fr)
|
516
516
|
assert np.all(cts_np == cts_fr)
|
517
517
|
|
@@ -684,4 +684,80 @@ def test_widen_dtype():
|
|
684
684
|
assert fastremap.widen_dtype(np.complex128, exotics=True) == np.clongdouble
|
685
685
|
assert fastremap.widen_dtype(np.clongdouble, exotics=True) == np.clongdouble
|
686
686
|
|
687
|
+
def test_unique_order():
|
688
|
+
data = np.array([
|
689
|
+
1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
690
|
+
1704, 1704, 1704, 1704, 1704, 1704, 106, 106, 106, 106, 106,
|
691
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
692
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
693
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
694
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
695
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
696
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
697
|
+
106, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
698
|
+
1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
699
|
+
1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
700
|
+
1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
701
|
+
1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
702
|
+
1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
703
|
+
1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
704
|
+
1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
705
|
+
1704, 1704, 1704, 1704, 1704, 106, 106, 106, 106, 106, 106,
|
706
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
707
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
708
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
709
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
710
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
711
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
712
|
+
106, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
713
|
+
1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
714
|
+
1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
715
|
+
1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704, 1704,
|
716
|
+
1704, 1704, 1704, 106, 106, 106, 106, 106, 106, 106, 106,
|
717
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
718
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
719
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
720
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
721
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
722
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
723
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
724
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
725
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
726
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
727
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
728
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
729
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
730
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
731
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
732
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
733
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
734
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
735
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
736
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
737
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
738
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
739
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
740
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
741
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
742
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
743
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
744
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
745
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
746
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
747
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
748
|
+
106, 106, 106, 106, 106, 106, 106, 1873, 106, 106, 106,
|
749
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
750
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
751
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
752
|
+
106, 106, 106, 106, 1873, 1873, 106, 106, 106, 106, 106,
|
753
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
754
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
755
|
+
106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
|
756
|
+
106, 1873, 1873, 106, 106, 106, 106, 106, 106, 106, 106,
|
757
|
+
106, 106, 106, 106, 106, 106, 106
|
758
|
+
])
|
759
|
+
tup = fastremap.unique(data, return_counts=True, return_index=True, return_inverse=True)
|
760
|
+
tup2 = np.unique(data, return_counts=True, return_index=True, return_inverse=True)
|
687
761
|
|
762
|
+
for res, ans in zip(tup, tup2):
|
763
|
+
assert np.all(res == ans)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
from .fastremap import (
|
2
|
+
ascontiguousarray,
|
3
|
+
asfortranarray,
|
4
|
+
component_map,
|
5
|
+
fit_dtype,
|
6
|
+
foreground,
|
7
|
+
indices,
|
8
|
+
inverse_component_map,
|
9
|
+
mask,
|
10
|
+
mask_except,
|
11
|
+
minmax,
|
12
|
+
narrow_dtype,
|
13
|
+
pixel_pairs,
|
14
|
+
point_cloud,
|
15
|
+
refit,
|
16
|
+
remap,
|
17
|
+
remap_from_array,
|
18
|
+
remap_from_array_kv,
|
19
|
+
renumber,
|
20
|
+
tobytes,
|
21
|
+
transpose,
|
22
|
+
unique,
|
23
|
+
widen_dtype,
|
24
|
+
)
|
25
|
+
|
26
|
+
__all__ = [
|
27
|
+
"ascontiguousarray",
|
28
|
+
"asfortranarray",
|
29
|
+
"component_map",
|
30
|
+
"fit_dtype",
|
31
|
+
"foreground",
|
32
|
+
"indices",
|
33
|
+
"inverse_component_map",
|
34
|
+
"mask",
|
35
|
+
"mask_except",
|
36
|
+
"minmax",
|
37
|
+
"narrow_dtype",
|
38
|
+
"pixel_pairs",
|
39
|
+
"point_cloud",
|
40
|
+
"refit",
|
41
|
+
"remap",
|
42
|
+
"remap_from_array",
|
43
|
+
"remap_from_array_kv",
|
44
|
+
"renumber",
|
45
|
+
"tobytes",
|
46
|
+
"transpose",
|
47
|
+
"unique",
|
48
|
+
"widen_dtype",
|
49
|
+
]
|