easyidp 2.0.0__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.
Files changed (36) hide show
  1. easyidp-2.0.0/LICENSE +21 -0
  2. easyidp-2.0.0/PKG-INFO +147 -0
  3. easyidp-2.0.0/README.md +90 -0
  4. easyidp-2.0.0/easyidp/__init__.py +241 -0
  5. easyidp-2.0.0/easyidp/cvtools.py +356 -0
  6. easyidp-2.0.0/easyidp/data.py +746 -0
  7. easyidp-2.0.0/easyidp/geotiff.py +1719 -0
  8. easyidp-2.0.0/easyidp/geotools.py +280 -0
  9. easyidp-2.0.0/easyidp/jsonfile.py +579 -0
  10. easyidp-2.0.0/easyidp/metashape.py +1999 -0
  11. easyidp-2.0.0/easyidp/pix4d.py +1903 -0
  12. easyidp-2.0.0/easyidp/pointcloud.py +1298 -0
  13. easyidp-2.0.0/easyidp/reconstruct.py +776 -0
  14. easyidp-2.0.0/easyidp/roi.py +1184 -0
  15. easyidp-2.0.0/easyidp/shp.py +472 -0
  16. easyidp-2.0.0/easyidp/visualize.py +349 -0
  17. easyidp-2.0.0/easyidp.egg-info/PKG-INFO +147 -0
  18. easyidp-2.0.0/easyidp.egg-info/SOURCES.txt +35 -0
  19. easyidp-2.0.0/easyidp.egg-info/dependency_links.txt +1 -0
  20. easyidp-2.0.0/easyidp.egg-info/requires.txt +33 -0
  21. easyidp-2.0.0/easyidp.egg-info/top_level.txt +2 -0
  22. easyidp-2.0.0/setup.cfg +7 -0
  23. easyidp-2.0.0/setup.py +65 -0
  24. easyidp-2.0.0/tests/__init__.py +30 -0
  25. easyidp-2.0.0/tests/test_cvtools.py +387 -0
  26. easyidp-2.0.0/tests/test_data.py +39 -0
  27. easyidp-2.0.0/tests/test_geotiff.py +636 -0
  28. easyidp-2.0.0/tests/test_init_class_func.py +135 -0
  29. easyidp-2.0.0/tests/test_jsonfile.py +132 -0
  30. easyidp-2.0.0/tests/test_metashape.py +852 -0
  31. easyidp-2.0.0/tests/test_pix4d.py +297 -0
  32. easyidp-2.0.0/tests/test_pointcloud.py +524 -0
  33. easyidp-2.0.0/tests/test_reconstruct.py +328 -0
  34. easyidp-2.0.0/tests/test_roi.py +349 -0
  35. easyidp-2.0.0/tests/test_shp.py +241 -0
  36. easyidp-2.0.0/tests/test_visualize.py +117 -0
easyidp-2.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 UTokyo-FieldPhenomics-Lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
easyidp-2.0.0/PKG-INFO ADDED
@@ -0,0 +1,147 @@
1
+ Metadata-Version: 2.1
2
+ Name: easyidp
3
+ Version: 2.0.0
4
+ Summary: A handy tool for dealing with region of interest (ROI) on the image reconstruction (Metashape & Pix4D) outputs, mainly in agriculture applications
5
+ Home-page: https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP
6
+ Author: Haozhou Wang
7
+ Author-email: howcanoewang@gmail.com
8
+ Project-URL: Documentation, https://easyidp.readthedocs.io/en/latest/
9
+ Project-URL: Source, https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP
10
+ Project-URL: Tracker, https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/issues
11
+ Project-URL: forum, https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/discussions
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Topic :: Scientific/Engineering :: GIS
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.7
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3 :: Only
24
+ Requires-Python: >=3.7, <4
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: numpy>=1.18.1
28
+ Requires-Dist: matplotlib>=3.2.2
29
+ Requires-Dist: scikit-image>=0.19.2
30
+ Requires-Dist: tabulate>=0.8.9
31
+ Requires-Dist: tqdm>=4.64.0
32
+ Requires-Dist: pyproj>=3.4.0
33
+ Requires-Dist: tifffile>=2020.09.03
34
+ Requires-Dist: imagecodecs>=2021.11.20
35
+ Requires-Dist: shapely~=1.8.0
36
+ Requires-Dist: lazrs>=0.1.1
37
+ Requires-Dist: laspy>=2.1.2
38
+ Requires-Dist: plyfile==0.7.2
39
+ Requires-Dist: pyshp==2.1.3
40
+ Requires-Dist: geojson>=3.1.0
41
+ Requires-Dist: gdown>=4.7.3
42
+ Provides-Extra: docs
43
+ Requires-Dist: sphinx==5.3.0; extra == "docs"
44
+ Requires-Dist: sphinx-intl==2.0.1; extra == "docs"
45
+ Requires-Dist: sphinx-inline-tabs==2022.1.2b11; extra == "docs"
46
+ Requires-Dist: furo==2022.12.7; extra == "docs"
47
+ Requires-Dist: nbsphinx==0.8.11; extra == "docs"
48
+ Requires-Dist: sphinx-gallery==0.10.1; extra == "docs"
49
+ Requires-Dist: ipython==8.10.0; extra == "docs"
50
+ Provides-Extra: test
51
+ Requires-Dist: pytest>=7.1.2; extra == "test"
52
+ Provides-Extra: build
53
+ Requires-Dist: packaging>=20.0; extra == "build"
54
+ Requires-Dist: wheel; extra == "build"
55
+ Requires-Dist: numpy>=1.19; extra == "build"
56
+ Requires-Dist: build; extra == "build"
57
+
58
+ <div align="center">
59
+
60
+ <p>
61
+ <!-- <a align="left" href="https://ultralytics.com/yolov5" target="_blank"> -->
62
+ <img width="850" src="https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/raw/v2.0/docs/_static/images/header_v2.0.png"></a>
63
+ </p>
64
+
65
+ <p align="center">
66
+ <img alt="GitHub Actions Badge" src="https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/actions/workflows/pytest.yml/badge.svg?style=plastic">
67
+ <img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/easyidp?style=plastic">
68
+ <img alt="GitHub" src="https://img.shields.io/github/license/UTokyo-FieldPhenomics-Lab/EasyIDP?style=plastic">
69
+ <img alt="GitHub top language" src="https://img.shields.io/github/languages/top/UTokyo-FieldPhenomics-Lab/EasyIDP?style=plastic">
70
+ <img alt="GitHub Downloads" src="https://img.shields.io/github/downloads/UTokyo-FieldPhenomics-Lab/EasyIDP/total?label=github%20downloads&style=plastic">
71
+ <img alt="GitHub Downloads" src="https://img.shields.io/pypi/dm/easyidp?color=%233775A9&label=pypi%20downloads&style=plastic">
72
+ </p>
73
+
74
+ </div>
75
+
76
+ EasyIDP (Easy Intermediate Data Processor), A handy tool for dealing with region of interest (ROI) on the image reconstruction (Metashape & Pix4D) outputs, mainly in agriculture applications. It provides the following functions:
77
+
78
+ 1. Backward Projection ROI to original images (`Backward Projector`).
79
+ 2. Crop ROI on GeoTiff Maps (DOM & DSM) and Point Cloud (`ROI Cropper`).
80
+ 3. Save cropped results to corresponding files (`ROI Saver`).
81
+
82
+ This project tried to use packges based on pure-python, instead of installing some heavy packages (Open3D, OpenCV) and hard to install packages (GDAL dependices) for one or two individual functions. This may cause efficiency loss and differences in coding habit.
83
+
84
+ <p align="center">
85
+ <img alt="GitHub Downloads" height="400px" src="https://api.star-history.com/svg?repos=UTokyo-FieldPhenomics-Lab/EasyIDP&type=Date">
86
+ </p>
87
+
88
+ ## <div align="center">Documentation</div>
89
+
90
+ Please check [Official Documents](https://easyidp.readthedocs.io/en/latest/) ( [中文](https://easyidp.readthedocs.io/zh_CN/latest/) | [日本語(翻訳募集)](https://easyidp.readthedocs.io/ja/latest/) ) for full documentations. And please also use the [Github Discussion](https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/discussions) when you meet any problems.
91
+
92
+ ## <div align="center">References</div>
93
+
94
+ Please cite this paper if this project helps you:
95
+
96
+ ```latex
97
+ @Article{wang_easyidp_2021,
98
+ AUTHOR = {Wang, Haozhou and Duan, Yulin and Shi, Yun and Kato, Yoichiro and Ninomiya, Seish and Guo, Wei},
99
+ TITLE = {EasyIDP: A Python Package for Intermediate Data Processing in UAV-Based Plant Phenotyping},
100
+ JOURNAL = {Remote Sensing},
101
+ VOLUME = {13},
102
+ YEAR = {2021},
103
+ NUMBER = {13},
104
+ ARTICLE-NUMBER = {2622},
105
+ URL = {https://www.mdpi.com/2072-4292/13/13/2622},
106
+ ISSN = {2072-4292},
107
+ DOI = {10.3390/rs13132622}
108
+ }
109
+ ```
110
+
111
+ We also thanks the benefits from the following open source projects:
112
+
113
+ * package main (**for users**)
114
+ * numpy: [https://numpy.org/](https://numpy.org/)
115
+ * matplotlib:[https://matplotlib.org/](https://matplotlib.org/)
116
+ * scikit-image: [https://github.com/scikit-image/scikit-image](https://github.com/scikit-image/scikit-image)
117
+ * pyproj: [https://github.com/pyproj4/pyproj](https://github.com/pyproj4/pyproj)
118
+ * tifffile: [https://github.com/cgohlke/tifffile](https://github.com/cgohlke/tifffile)
119
+ * imagecodecs: [https://github.com/cgohlke/imagecodecs](https://github.com/cgohlke/imagecodecs)
120
+ * shapely: [https://github.com/shapely/shapely](https://github.com/shapely/shapely)
121
+ * laspy/lasrs/lasio: [https://github.com/laspy/laspy](https://github.com/laspy/laspy)
122
+ * geojson: [https://github.com/jazzband/geojson](https://github.com/jazzband/geojson)
123
+ * plyfile: [https://github.com/dranjan/python-plyfile](https://github.com/dranjan/python-plyfile)
124
+ * pyshp: [https://github.com/GeospatialPython/pyshp](https://github.com/GeospatialPython/pyshp)
125
+ * tabulate: [https://github.com/astanin/python-tabulate](https://github.com/astanin/python-tabulate)
126
+ * tqdm: [https://github.com/tqdm/tqdm](https://github.com/tqdm/tqdm)
127
+ * gdown: [https://github.com/wkentaro/gdown](https://github.com/wkentaro/gdown)
128
+ * package documentation (**for developers**)
129
+ * sphinx: [https://github.com/sphinx-doc/sphinx](https://github.com/sphinx-doc/sphinx)
130
+ * nbsphinx: [https://github.com/spatialaudio/nbsphinx](https://github.com/spatialaudio/nbsphinx)
131
+ * sphinx-gallery: [https://github.com/sphinx-gallery/sphinx-gallery](https://github.com/sphinx-gallery/sphinx-gallery)
132
+ * sphinx-inline-tabs: [https://github.com/pradyunsg/sphinx-inline-tabs](https://github.com/pradyunsg/sphinx-inline-tabs)
133
+ * sphinx-intl: [https://github.com/sphinx-doc/sphinx-intl](https://github.com/sphinx-doc/sphinx-intl)
134
+ * sphinx-rtc-theme: [https://github.com/readthedocs/sphinx_rtd_theme](https://github.com/readthedocs/sphinx_rtd_theme)
135
+ * furo: [https://github.com/pradyunsg/furo](https://github.com/pradyunsg/furo)
136
+ * package testing and releasing (**for developers**)
137
+ * pytest: [https://github.com/pytest-dev/pytest](https://github.com/pytest-dev/pytest)
138
+ * packaging: [https://github.com/pypa/packaging](https://github.com/pypa/packaging)
139
+ * wheel: [https://github.com/pypa/wheel](https://github.com/pypa/wheel)
140
+
141
+ This project was partially funded by:
142
+
143
+ * the JST AIP Acceleration Research “Studies of CPS platform to raise big-data-driven AI agriculture”;
144
+ * the SICORP Program JPMJSC16H2;
145
+ * CREST Programs JPMJCR16O2 and JPMJCR16O1;
146
+ * the International Science & Technology Innovation Program of Chinese Academy of Agricultural Sciences (CAASTIP);
147
+ * the National Natural Science Foundation of China U19A2061.
@@ -0,0 +1,90 @@
1
+ <div align="center">
2
+
3
+ <p>
4
+ <!-- <a align="left" href="https://ultralytics.com/yolov5" target="_blank"> -->
5
+ <img width="850" src="https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/raw/v2.0/docs/_static/images/header_v2.0.png"></a>
6
+ </p>
7
+
8
+ <p align="center">
9
+ <img alt="GitHub Actions Badge" src="https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/actions/workflows/pytest.yml/badge.svg?style=plastic">
10
+ <img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/easyidp?style=plastic">
11
+ <img alt="GitHub" src="https://img.shields.io/github/license/UTokyo-FieldPhenomics-Lab/EasyIDP?style=plastic">
12
+ <img alt="GitHub top language" src="https://img.shields.io/github/languages/top/UTokyo-FieldPhenomics-Lab/EasyIDP?style=plastic">
13
+ <img alt="GitHub Downloads" src="https://img.shields.io/github/downloads/UTokyo-FieldPhenomics-Lab/EasyIDP/total?label=github%20downloads&style=plastic">
14
+ <img alt="GitHub Downloads" src="https://img.shields.io/pypi/dm/easyidp?color=%233775A9&label=pypi%20downloads&style=plastic">
15
+ </p>
16
+
17
+ </div>
18
+
19
+ EasyIDP (Easy Intermediate Data Processor), A handy tool for dealing with region of interest (ROI) on the image reconstruction (Metashape & Pix4D) outputs, mainly in agriculture applications. It provides the following functions:
20
+
21
+ 1. Backward Projection ROI to original images (`Backward Projector`).
22
+ 2. Crop ROI on GeoTiff Maps (DOM & DSM) and Point Cloud (`ROI Cropper`).
23
+ 3. Save cropped results to corresponding files (`ROI Saver`).
24
+
25
+ This project tried to use packges based on pure-python, instead of installing some heavy packages (Open3D, OpenCV) and hard to install packages (GDAL dependices) for one or two individual functions. This may cause efficiency loss and differences in coding habit.
26
+
27
+ <p align="center">
28
+ <img alt="GitHub Downloads" height="400px" src="https://api.star-history.com/svg?repos=UTokyo-FieldPhenomics-Lab/EasyIDP&type=Date">
29
+ </p>
30
+
31
+ ## <div align="center">Documentation</div>
32
+
33
+ Please check [Official Documents](https://easyidp.readthedocs.io/en/latest/) ( [中文](https://easyidp.readthedocs.io/zh_CN/latest/) | [日本語(翻訳募集)](https://easyidp.readthedocs.io/ja/latest/) ) for full documentations. And please also use the [Github Discussion](https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/discussions) when you meet any problems.
34
+
35
+ ## <div align="center">References</div>
36
+
37
+ Please cite this paper if this project helps you:
38
+
39
+ ```latex
40
+ @Article{wang_easyidp_2021,
41
+ AUTHOR = {Wang, Haozhou and Duan, Yulin and Shi, Yun and Kato, Yoichiro and Ninomiya, Seish and Guo, Wei},
42
+ TITLE = {EasyIDP: A Python Package for Intermediate Data Processing in UAV-Based Plant Phenotyping},
43
+ JOURNAL = {Remote Sensing},
44
+ VOLUME = {13},
45
+ YEAR = {2021},
46
+ NUMBER = {13},
47
+ ARTICLE-NUMBER = {2622},
48
+ URL = {https://www.mdpi.com/2072-4292/13/13/2622},
49
+ ISSN = {2072-4292},
50
+ DOI = {10.3390/rs13132622}
51
+ }
52
+ ```
53
+
54
+ We also thanks the benefits from the following open source projects:
55
+
56
+ * package main (**for users**)
57
+ * numpy: [https://numpy.org/](https://numpy.org/)
58
+ * matplotlib:[https://matplotlib.org/](https://matplotlib.org/)
59
+ * scikit-image: [https://github.com/scikit-image/scikit-image](https://github.com/scikit-image/scikit-image)
60
+ * pyproj: [https://github.com/pyproj4/pyproj](https://github.com/pyproj4/pyproj)
61
+ * tifffile: [https://github.com/cgohlke/tifffile](https://github.com/cgohlke/tifffile)
62
+ * imagecodecs: [https://github.com/cgohlke/imagecodecs](https://github.com/cgohlke/imagecodecs)
63
+ * shapely: [https://github.com/shapely/shapely](https://github.com/shapely/shapely)
64
+ * laspy/lasrs/lasio: [https://github.com/laspy/laspy](https://github.com/laspy/laspy)
65
+ * geojson: [https://github.com/jazzband/geojson](https://github.com/jazzband/geojson)
66
+ * plyfile: [https://github.com/dranjan/python-plyfile](https://github.com/dranjan/python-plyfile)
67
+ * pyshp: [https://github.com/GeospatialPython/pyshp](https://github.com/GeospatialPython/pyshp)
68
+ * tabulate: [https://github.com/astanin/python-tabulate](https://github.com/astanin/python-tabulate)
69
+ * tqdm: [https://github.com/tqdm/tqdm](https://github.com/tqdm/tqdm)
70
+ * gdown: [https://github.com/wkentaro/gdown](https://github.com/wkentaro/gdown)
71
+ * package documentation (**for developers**)
72
+ * sphinx: [https://github.com/sphinx-doc/sphinx](https://github.com/sphinx-doc/sphinx)
73
+ * nbsphinx: [https://github.com/spatialaudio/nbsphinx](https://github.com/spatialaudio/nbsphinx)
74
+ * sphinx-gallery: [https://github.com/sphinx-gallery/sphinx-gallery](https://github.com/sphinx-gallery/sphinx-gallery)
75
+ * sphinx-inline-tabs: [https://github.com/pradyunsg/sphinx-inline-tabs](https://github.com/pradyunsg/sphinx-inline-tabs)
76
+ * sphinx-intl: [https://github.com/sphinx-doc/sphinx-intl](https://github.com/sphinx-doc/sphinx-intl)
77
+ * sphinx-rtc-theme: [https://github.com/readthedocs/sphinx_rtd_theme](https://github.com/readthedocs/sphinx_rtd_theme)
78
+ * furo: [https://github.com/pradyunsg/furo](https://github.com/pradyunsg/furo)
79
+ * package testing and releasing (**for developers**)
80
+ * pytest: [https://github.com/pytest-dev/pytest](https://github.com/pytest-dev/pytest)
81
+ * packaging: [https://github.com/pypa/packaging](https://github.com/pypa/packaging)
82
+ * wheel: [https://github.com/pypa/wheel](https://github.com/pypa/wheel)
83
+
84
+ This project was partially funded by:
85
+
86
+ * the JST AIP Acceleration Research “Studies of CPS platform to raise big-data-driven AI agriculture”;
87
+ * the SICORP Program JPMJSC16H2;
88
+ * CREST Programs JPMJCR16O2 and JPMJCR16O1;
89
+ * the International Science & Technology Innovation Program of Chinese Academy of Agricultural Sciences (CAASTIP);
90
+ * the National Natural Science Foundation of China U19A2061.
@@ -0,0 +1,241 @@
1
+ __version__ = "2.0.0"
2
+
3
+ import os
4
+ import warnings
5
+ import numpy as np
6
+ from pathlib import Path
7
+
8
+ from copy import deepcopy
9
+
10
+ ##############
11
+ # dict tools #
12
+ ##############
13
+
14
+ class Container(dict):
15
+ """Self designed dictionary class to fetch items by id or label
16
+
17
+ Caution
18
+ -------
19
+ This object can not be saved by ``pickle``, it will cause problem when loading [1]_
20
+
21
+ References
22
+ ----------
23
+ .. [1] https://stackoverflow.com/questions/4014621/a-python-class-that-acts-like-dict
24
+ """
25
+ def __init__(self, suffix=''):
26
+ super().__init__()
27
+ self.id_item = {} # {0: item1, 1: item2}
28
+ self.item_label = {} #{"N1W1": 0, "N1W2": 1}, just index it position
29
+ self._suffix = str(suffix)
30
+
31
+ def __setitem__(self, key, item):
32
+ if isinstance(key, int):
33
+ # default method to set values
34
+ # Container[0] = A, while A.label = "N1W1"
35
+
36
+ if key < len(self.item_label):
37
+ if 'label' in dir(item): # has item.label
38
+ # delete old label
39
+ # e.g. {'empty 0': 0, 'empty 1': 1}
40
+ # 0 -> IMG_0001;
41
+ # {'empty 0': 0, 'empty 1': 1, 'IMG_0001': 0}
42
+ old_key = self.id_item[key].label
43
+ del self.item_label[old_key]
44
+
45
+ # add new label
46
+ self.item_label[item.label] = key
47
+ # change the value of one item
48
+ self.id_item[key] = item
49
+
50
+ elif key == len(self.item_label):
51
+ # add a new item
52
+ self.id_item[key] = item
53
+ if 'label' in dir(item):
54
+ # sometimes two items has the same label
55
+ if item.label in self.item_label.keys():
56
+ raise KeyError(f"The given item's label [{item.label}] already exists -> {self.item_label.keys()}")
57
+ else:
58
+ self.item_label[item.label] = key
59
+ else:
60
+ self.item_label[key] = key
61
+ else:
62
+ raise IndexError(f"Index [{key}] out of range (0, {len(self.item_label)})")
63
+
64
+ elif isinstance(key, str):
65
+ # advanced method to change items
66
+ # Container["N1W1"] = B, here assuemt B.label already == "N1W1"
67
+
68
+ # item already exists
69
+ if key in self.item_label.keys():
70
+ idx = self.item_label[key]
71
+ self.id_item[idx] = item
72
+ else: # add new item
73
+ idx = len(self.id_item)
74
+ self.id_item[idx] = item
75
+ if 'label' in dir(item): # has item.label
76
+ self.item_label[item.label] = idx
77
+ else: # act as common dictionary
78
+ self.item_label[key] = idx
79
+ else:
80
+ raise KeyError(f"Key should be 'int', 'str', not {key}")
81
+
82
+ def __getitem__(self, key):
83
+ if isinstance(key, int): # index by photo order
84
+ if key < len(self.item_label):
85
+ return self.id_item[key]
86
+ else:
87
+ raise IndexError(f"Index [{key}] out of range (0, {len(self.item_label)})")
88
+ elif isinstance(key, str): # index by photo name
89
+ if key in self.item_label.keys():
90
+ return self.id_item[self.item_label[key]]
91
+ elif self._suffix in key and os.path.splitext(key)[0] in self.item_label.keys():
92
+ return self.id_item[self.item_label[os.path.splitext(key)[0]]]
93
+ else:
94
+ raise KeyError(f"Can not find key [{key}]")
95
+ elif isinstance(key, slice):
96
+ idx_list = list(self.id_item.keys())[key]
97
+
98
+ out = self.copy()
99
+ out.id_item = {k:v for k, v in self.id_item.items() if k in idx_list}
100
+ out.item_label = {k:v for k, v in self.item_label.items() if v in idx_list}
101
+
102
+ return out
103
+ else:
104
+ raise KeyError(f"Key should be 'int', 'str', 'slice', not {key}")
105
+
106
+ def __repr__(self) -> str:
107
+ return self._btf_print()
108
+
109
+ def __str__(self) -> str:
110
+ return self._btf_print()
111
+
112
+ def _btf_print(self):
113
+ title = f'easyidp.{self.__class__.__name__}'
114
+ key_list = list(self.item_label.keys())
115
+ num = len(key_list)
116
+ out_str = f'<{title}> with {num} items\n'
117
+
118
+ # limit the numpy print out
119
+ default_np_thresh = np.get_printoptions()['threshold']
120
+ default_np_suppress = np.get_printoptions()['suppress']
121
+ np.set_printoptions(threshold=4, suppress=True)
122
+ if num == 0:
123
+ out_str = "<Empty easyidp.Container object>"
124
+ elif num > 5:
125
+ for i, k in enumerate(key_list[:2]):
126
+ out_str += f"[{i}]\t{k}\n"
127
+ out_str += repr(self.id_item[self.item_label[k]])
128
+ out_str += '\n'
129
+ out_str += '...\n'
130
+ for i, k in enumerate(key_list[-2:]):
131
+ out_str += f"[{num-2+i}]\t{k}\n"
132
+ out_str += repr(self.id_item[self.item_label[k]])
133
+ out_str += '\n'
134
+ else:
135
+ for i, k in enumerate(key_list):
136
+ out_str += f"[{i}]\t{k}\n"
137
+ out_str += repr(self.id_item[self.item_label[k]])
138
+ out_str += '\n'
139
+ np.set_printoptions(threshold=default_np_thresh, suppress=default_np_suppress)
140
+
141
+ out_str = out_str[:-1]
142
+ return out_str
143
+
144
+ def __len__(self):
145
+ return len(self.id_item)
146
+
147
+ def __delitem__(self, key):
148
+ if isinstance(key, int):
149
+ k = key
150
+ del self.item_label[self.id_item[key]]
151
+ del self.id_item[key]
152
+ elif isinstance(key, str):
153
+ k = self.item_label[key]
154
+ del self.id_item[self.item_label[key]]
155
+ del self.item_label[key]
156
+ else:
157
+ raise KeyError(f"Key should be 'int', 'str', 'slice', not {key}")
158
+
159
+ # update the id
160
+ # a[5] = a.pop(1)
161
+ # https://stackoverflow.com/questions/4406501/change-the-name-of-a-key-in-dictionary
162
+ id_item_keys = list(self.id_item.keys())
163
+ for idx in id_item_keys:
164
+ # e,g. k = 3, idx in [0, 1, 2, 4, 5]
165
+ if idx > k:
166
+ self.id_item[idx-1] = self.id_item.pop(idx)
167
+
168
+ # e.g. {"N1W1": 0, "N1W2": 1},
169
+ label = _find_key(self.item_label, idx)
170
+ self.item_label[label] = idx - 1
171
+
172
+ def __iter__(self):
173
+ return iter(self.id_item.values())
174
+
175
+ def keys(self):
176
+ return self.item_label.keys()
177
+
178
+ def values(self):
179
+ return self.id_item.values()
180
+
181
+ def items(self):
182
+ out_dict = {}
183
+ for k, idx in self.item_label.items():
184
+ out_dict[k] = self.id_item[idx]
185
+ return out_dict.items()
186
+
187
+ def copy(self):
188
+ return deepcopy(self)
189
+
190
+
191
+ def _find_key(mydict, value):
192
+ """a simple function to using dict value to find key
193
+ e.g.
194
+ >>> mydict = {"a": 233, "b": 456}
195
+ >>> _find_key(mydict, 233)
196
+ "a"
197
+ """
198
+ key_idx = list(mydict.values()).index(value)
199
+ return list(mydict.keys())[key_idx]
200
+
201
+
202
+ ##############
203
+ # path tools #
204
+ ##############
205
+
206
+ def get_full_path(short_path):
207
+ if isinstance(short_path, str):
208
+ return Path(short_path)
209
+ elif isinstance(short_path, Path):
210
+ return short_path
211
+ else:
212
+ return None
213
+
214
+ def parse_relative_path(root_path, relative_path):
215
+ # for metashape frame.zip path use only
216
+ if r"../../" in relative_path:
217
+ frame_path = os.path.dirname(os.path.abspath(root_path))
218
+ merge = os.path.join(frame_path, relative_path)
219
+ return os.path.abspath(merge)
220
+ else:
221
+ warnings.warn(f"Seems it is an absolute path [{relative_path}]")
222
+ return relative_path
223
+
224
+ ###############
225
+ # import APIs #
226
+ ###############
227
+
228
+ from . import (
229
+ visualize,
230
+ cvtools,
231
+ geotools,
232
+ shp,
233
+ jsonfile,
234
+ data,
235
+ )
236
+ from .reconstruct import ProjectPool
237
+ from .pointcloud import PointCloud
238
+ from .geotiff import GeoTiff
239
+ from .pix4d import Pix4D
240
+ from .metashape import Metashape
241
+ from .roi import ROI