PyOPIA 1.0.0__tar.gz → 1.1.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.
- {pyopia-1.0.0 → pyopia-1.1.0}/PKG-INFO +13 -10
- {pyopia-1.0.0 → pyopia-1.1.0}/README.md +3 -7
- pyopia-1.1.0/pyopia/CITATION.cff +38 -0
- pyopia-1.1.0/pyopia/__init__.py +1 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/classify.py +16 -6
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/pipeline.py +1 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/process.py +45 -18
- {pyopia-1.0.0 → pyopia-1.1.0}/pyproject.toml +16 -3
- pyopia-1.0.0/pyopia/__init__.py +0 -1
- {pyopia-1.0.0 → pyopia-1.1.0}/LICENSE +0 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/background.py +0 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/cli.py +0 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/instrument/__init__.py +0 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/instrument/holo.py +0 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/instrument/silcam.py +0 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/io.py +0 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/plotting.py +0 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/statistics.py +0 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/tests/__init__.py +0 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/tests/test_pipeline.py +0 -0
- {pyopia-1.0.0 → pyopia-1.1.0}/pyopia/tests/testdata.py +0 -0
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyOPIA
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: A Python Ocean Particle Image Analysis toolbox.
|
|
5
|
+
Home-page: https://github.com/sintef/pyopia
|
|
6
|
+
Keywords: Ocean,Particles,Imaging,Measurement,Size distribution
|
|
5
7
|
Author: Emlyn Davies
|
|
6
8
|
Author-email: emlyn.davies@sintef.no
|
|
7
9
|
Requires-Python: >=3.10,<3.11
|
|
8
10
|
Classifier: Programming Language :: Python :: 3
|
|
9
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Provides-Extra: classification
|
|
13
|
+
Provides-Extra: classification-arm64
|
|
10
14
|
Requires-Dist: cmocean (>=3.0.3,<4.0.0)
|
|
11
15
|
Requires-Dist: flake8 (>=6.1.0,<7.0.0)
|
|
12
16
|
Requires-Dist: gdown (>=4.7.1,<5.0.0)
|
|
@@ -30,13 +34,16 @@ Requires-Dist: sphinx-copybutton (>=0.5.2,<0.6.0)
|
|
|
30
34
|
Requires-Dist: sphinx-rtd-theme (>=0.5.0)
|
|
31
35
|
Requires-Dist: sphinx-togglebutton (>=0.3.2,<0.4.0)
|
|
32
36
|
Requires-Dist: sphinxcontrib-napoleon (>=0.7)
|
|
33
|
-
Requires-Dist: tensorflow-cpu (==2.11.0)
|
|
34
|
-
Requires-Dist: tensorflow-io-gcs-filesystem (
|
|
37
|
+
Requires-Dist: tensorflow-cpu (==2.11.0) ; extra == "classification"
|
|
38
|
+
Requires-Dist: tensorflow-io-gcs-filesystem (>=0.31.0) ; extra == "classification-arm64" or extra == "classification"
|
|
39
|
+
Requires-Dist: tensorflow-macos (==2.11.0) ; (sys_platform == "darwin" and platform_machine == "arm64") and (extra == "classification-arm64")
|
|
35
40
|
Requires-Dist: toml (>=0.10.2,<0.11.0)
|
|
36
41
|
Requires-Dist: tqdm (>=4.66.1,<5.0.0)
|
|
37
42
|
Requires-Dist: typer[all] (>=0.9.0,<0.10.0)
|
|
38
43
|
Requires-Dist: urllib3 (<2.0)
|
|
39
44
|
Requires-Dist: xarray (>=2023.8.0,<2024.0.0)
|
|
45
|
+
Project-URL: Documentation, https://pyopia.readthedocs.io
|
|
46
|
+
Project-URL: Repository, https://github.com/sintef/pyopia
|
|
40
47
|
Description-Content-Type: text/markdown
|
|
41
48
|
|
|
42
49
|
PyOpia
|
|
@@ -53,18 +60,14 @@ A Python Ocean Particle Image Analysis toolbox
|
|
|
53
60
|
|
|
54
61
|
- Under development. See/regester issues, [here](https://github.com/SINTEF/pyopia/issues)
|
|
55
62
|
|
|
56
|
-
- Refining a structure for a standard [processing piplines](https://pyopia.readthedocs.io/en/latest/pyopia.pipeline.html)
|
|
57
|
-
|
|
58
|
-
- Building a system for metadata and [output files](https://pyopia.readthedocs.io/en/latest/pyopia.io.html)
|
|
59
|
-
|
|
60
63
|
----
|
|
61
64
|
|
|
62
65
|
# Installing for users
|
|
63
66
|
|
|
64
|
-
Users are expected to be familiar with Python, and have [Python](https://github.com/conda-forge/miniforge/#download), [pip](https://pypi.org/project/pip/)
|
|
67
|
+
Users are expected to be familiar with Python, and have [Python](https://github.com/conda-forge/miniforge/#download), [pip](https://pypi.org/project/pip/). You can then install Pyopia like this:
|
|
65
68
|
|
|
66
69
|
```
|
|
67
|
-
pip install
|
|
70
|
+
pip install pyopia
|
|
68
71
|
```
|
|
69
72
|
|
|
70
73
|
We would usually recommend installing within a virtual python environment, which you can read more about [here](https://jni.github.io/using-python-for-science/intro-to-environments.html).
|
|
@@ -98,7 +101,7 @@ We welcome additions and improvements to the code! We request that you follow a
|
|
|
98
101
|
4. All pull requests must be reviewed by a person. The benefits from code review are plenty, but we like to emphasise that code reviews help spreading the awarenes of code changes. Please note that code reviews should be a pleasant experience, so be plesant, polite and remember that there is a human being with good intentions on the other side of the screen.
|
|
99
102
|
5. All contributions are linted with flake8. We recommend that you run flake8 on your code while developing to fix any issues as you go. We recommend using autopep8 to autoformat your Python code (but please check the code behaviour is not affected by autoformatting before pushing). This makes flake8 happy, and makes it easier for us all to maintain a consistent and readable code base.
|
|
100
103
|
|
|
101
|
-
## Installing for developers
|
|
104
|
+
## Installing from source for developers
|
|
102
105
|
|
|
103
106
|
Install [Python](https://github.com/conda-forge/miniforge/#download).
|
|
104
107
|
|
|
@@ -12,18 +12,14 @@ A Python Ocean Particle Image Analysis toolbox
|
|
|
12
12
|
|
|
13
13
|
- Under development. See/regester issues, [here](https://github.com/SINTEF/pyopia/issues)
|
|
14
14
|
|
|
15
|
-
- Refining a structure for a standard [processing piplines](https://pyopia.readthedocs.io/en/latest/pyopia.pipeline.html)
|
|
16
|
-
|
|
17
|
-
- Building a system for metadata and [output files](https://pyopia.readthedocs.io/en/latest/pyopia.io.html)
|
|
18
|
-
|
|
19
15
|
----
|
|
20
16
|
|
|
21
17
|
# Installing for users
|
|
22
18
|
|
|
23
|
-
Users are expected to be familiar with Python, and have [Python](https://github.com/conda-forge/miniforge/#download), [pip](https://pypi.org/project/pip/)
|
|
19
|
+
Users are expected to be familiar with Python, and have [Python](https://github.com/conda-forge/miniforge/#download), [pip](https://pypi.org/project/pip/). You can then install Pyopia like this:
|
|
24
20
|
|
|
25
21
|
```
|
|
26
|
-
pip install
|
|
22
|
+
pip install pyopia
|
|
27
23
|
```
|
|
28
24
|
|
|
29
25
|
We would usually recommend installing within a virtual python environment, which you can read more about [here](https://jni.github.io/using-python-for-science/intro-to-environments.html).
|
|
@@ -57,7 +53,7 @@ We welcome additions and improvements to the code! We request that you follow a
|
|
|
57
53
|
4. All pull requests must be reviewed by a person. The benefits from code review are plenty, but we like to emphasise that code reviews help spreading the awarenes of code changes. Please note that code reviews should be a pleasant experience, so be plesant, polite and remember that there is a human being with good intentions on the other side of the screen.
|
|
58
54
|
5. All contributions are linted with flake8. We recommend that you run flake8 on your code while developing to fix any issues as you go. We recommend using autopep8 to autoformat your Python code (but please check the code behaviour is not affected by autoformatting before pushing). This makes flake8 happy, and makes it easier for us all to maintain a consistent and readable code base.
|
|
59
55
|
|
|
60
|
-
## Installing for developers
|
|
56
|
+
## Installing from source for developers
|
|
61
57
|
|
|
62
58
|
Install [Python](https://github.com/conda-forge/miniforge/#download).
|
|
63
59
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it as below."
|
|
3
|
+
authors:
|
|
4
|
+
- family-names: Davies
|
|
5
|
+
given-names: Emlyn
|
|
6
|
+
- family-names: Nimmo-Smith
|
|
7
|
+
given-names: Alex
|
|
8
|
+
- family-names: Nepstad
|
|
9
|
+
given-names: Raymond
|
|
10
|
+
- family-names: Nordam
|
|
11
|
+
given-names: Tor
|
|
12
|
+
- family-names: Brönner
|
|
13
|
+
given-names: Ute
|
|
14
|
+
- family-names: Steinvika
|
|
15
|
+
given-names: Andreas
|
|
16
|
+
- family-names: Sari
|
|
17
|
+
given-names: Giering
|
|
18
|
+
- family-names: Masoudi
|
|
19
|
+
given-names: Mojtaba
|
|
20
|
+
- family-names: Liu
|
|
21
|
+
given-names: Zonghua
|
|
22
|
+
- family-names: Hélaouët
|
|
23
|
+
given-names: Pierre
|
|
24
|
+
- family-names: Cursons
|
|
25
|
+
given-names: Kairan
|
|
26
|
+
- family-names: Rau
|
|
27
|
+
given-names: Matthew
|
|
28
|
+
- family-names: Song
|
|
29
|
+
given-names: Yixuan
|
|
30
|
+
- family-names: Mostaani
|
|
31
|
+
given-names: Arsalan
|
|
32
|
+
- family-names: Barstein
|
|
33
|
+
given-names: Karoline
|
|
34
|
+
- family-names: Buscombe
|
|
35
|
+
given-names: Daniel
|
|
36
|
+
title: "PyOPIA: A Python Ocean Particle Image Analysis toolbox"
|
|
37
|
+
url: "https://pyopia.readthedocs.io"
|
|
38
|
+
repository-code: "https://github.com/sintef/pyopia"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '1.1.0'
|
|
@@ -40,6 +40,16 @@ class Classify():
|
|
|
40
40
|
pipeline_class = 'pyopia.classify.Classify'
|
|
41
41
|
model_path = 'keras_model.h5' # path to trained nn model
|
|
42
42
|
|
|
43
|
+
If `[steps.classifier]`is not defined, the classification will be skipped and no probabilities reported.
|
|
44
|
+
|
|
45
|
+
If you want to use an example trained model for SilCam data
|
|
46
|
+
(no guarantee of accuracy for other applications), you can get it using `exampledata`
|
|
47
|
+
within the notebooks folder (https://github.com/SINTEF/pyopia/blob/main/notebooks/exampledata.py):
|
|
48
|
+
|
|
49
|
+
.. code-block:: python
|
|
50
|
+
|
|
51
|
+
model_path = exampledata.get_example_model()
|
|
52
|
+
|
|
43
53
|
'''
|
|
44
54
|
def __init__(self, model_path=None):
|
|
45
55
|
self.model_path = model_path
|
|
@@ -62,12 +72,12 @@ class Classify():
|
|
|
62
72
|
try:
|
|
63
73
|
from tensorflow import keras
|
|
64
74
|
except ImportError:
|
|
65
|
-
info_str = '
|
|
66
|
-
info_str += ' until you install tensorflow
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
info_str = 'ERROR: Could not import Keras. Classify will not work'
|
|
76
|
+
info_str += ' until you install tensorflow.\n'
|
|
77
|
+
info_str += 'Use: pip install pyopia[classification]\n'
|
|
78
|
+
info_str += ' or: pip install pyopia[classification-arm64]'
|
|
79
|
+
info_str += ' for tensorflow-macos (silicon chips)'
|
|
80
|
+
raise ImportError(info_str)
|
|
71
81
|
|
|
72
82
|
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
|
|
73
83
|
keras.backend.clear_session()
|
|
@@ -192,6 +192,29 @@ def write_segmented_images(imbw, imc, settings, timestamp):
|
|
|
192
192
|
imsave(fname, imc)
|
|
193
193
|
|
|
194
194
|
|
|
195
|
+
def put_roi_in_h5(export_outputpath, HDF5File, roi, filename, i):
|
|
196
|
+
'''Adds rois to an open hdf file if export_outputpath is not None.
|
|
197
|
+
For use within {func}`pyopia.process.export_particles`
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
export_outputpath : str
|
|
202
|
+
HDF5File : h5 file object
|
|
203
|
+
roi : uint8
|
|
204
|
+
i : int
|
|
205
|
+
particle number
|
|
206
|
+
|
|
207
|
+
Returns
|
|
208
|
+
-------
|
|
209
|
+
str
|
|
210
|
+
filename
|
|
211
|
+
'''
|
|
212
|
+
filename = filename + '-PN' + str(i)
|
|
213
|
+
if export_outputpath is not None:
|
|
214
|
+
HDF5File.create_dataset('PN' + str(i), data=roi)
|
|
215
|
+
return filename
|
|
216
|
+
|
|
217
|
+
|
|
195
218
|
def extract_particles(imc, timestamp, Classification, region_properties,
|
|
196
219
|
export_outputpath=None, min_length=0, propnames=['major_axis_length', 'minor_axis_length',
|
|
197
220
|
'equivalent_diameter']):
|
|
@@ -213,11 +236,12 @@ def extract_particles(imc, timestamp, Classification, region_properties,
|
|
|
213
236
|
'''
|
|
214
237
|
filenames = ['not_exported'] * len(region_properties)
|
|
215
238
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
239
|
+
if Classification is not None:
|
|
240
|
+
# pre-allocation
|
|
241
|
+
predictions = np.zeros((len(region_properties),
|
|
242
|
+
len(Classification.class_labels)),
|
|
243
|
+
dtype='float64')
|
|
244
|
+
predictions *= np.nan
|
|
221
245
|
|
|
222
246
|
# obtain the original image filename from the timestamp
|
|
223
247
|
filename = timestamp.strftime('D%Y%m%dT%H%M%S.%f')
|
|
@@ -239,6 +263,8 @@ def extract_particles(imc, timestamp, Classification, region_properties,
|
|
|
239
263
|
meta.attrs['Raw image name'] = filename
|
|
240
264
|
# @todo include more useful information in this meta data, e.g. possibly raw image location and background
|
|
241
265
|
# stack file list.
|
|
266
|
+
else:
|
|
267
|
+
HDF5File = None
|
|
242
268
|
|
|
243
269
|
# pre-allocate some things
|
|
244
270
|
data = np.zeros((len(region_properties), len(propnames)), dtype=np.float64)
|
|
@@ -258,15 +284,13 @@ def extract_particles(imc, timestamp, Classification, region_properties,
|
|
|
258
284
|
# extract the region of interest from the corrected colour image
|
|
259
285
|
roi = extract_roi(imc, bboxes[i, :].astype(int))
|
|
260
286
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
# @todo also include particle stats here too.
|
|
287
|
+
if Classification is not None:
|
|
288
|
+
# run a prediction on what type of particle this might be
|
|
289
|
+
prediction = Classification.proc_predict(roi.astype(np.uint8))
|
|
290
|
+
predictions[int(i), :] = prediction[0]
|
|
266
291
|
|
|
267
|
-
#
|
|
268
|
-
|
|
269
|
-
predictions[int(i), :] = prediction[0]
|
|
292
|
+
# add the roi to the HDF5 file
|
|
293
|
+
filenames[int(i)] = put_roi_in_h5(export_outputpath, HDF5File, roi, filename, i)
|
|
270
294
|
|
|
271
295
|
if export_outputpath is not None:
|
|
272
296
|
# close the HDF5 file
|
|
@@ -283,9 +307,10 @@ def extract_particles(imc, timestamp, Classification, region_properties,
|
|
|
283
307
|
|
|
284
308
|
print('EXTRACTING {0} IMAGES from {1}'.format(nb_extractable_part, len(stats['major_axis_length'])))
|
|
285
309
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
310
|
+
if Classification is not None:
|
|
311
|
+
# add classification predictions to the particle statistics data
|
|
312
|
+
for n, c in enumerate(Classification.class_labels):
|
|
313
|
+
stats['probability_' + c] = predictions[:, n]
|
|
289
314
|
|
|
290
315
|
# add the filenames of the HDF5 file and particle number tag to the
|
|
291
316
|
# particle statistics data
|
|
@@ -356,7 +381,8 @@ def segment(img, threshold=0.98, minimum_area=12, fill_holes=True):
|
|
|
356
381
|
return imbw
|
|
357
382
|
|
|
358
383
|
|
|
359
|
-
def statextract(imbw, timestamp, imc,
|
|
384
|
+
def statextract(imbw, timestamp, imc,
|
|
385
|
+
Classification=None,
|
|
360
386
|
max_coverage=30,
|
|
361
387
|
max_particles=5000,
|
|
362
388
|
export_outputpath=None,
|
|
@@ -510,7 +536,8 @@ class CalculateStats():
|
|
|
510
536
|
|
|
511
537
|
def __call__(self, data):
|
|
512
538
|
print('statextract')
|
|
513
|
-
stats, saturation = statextract(data['imbw'], data['timestamp'], data['imc'],
|
|
539
|
+
stats, saturation = statextract(data['imbw'], data['timestamp'], data['imc'],
|
|
540
|
+
Classification=data['cl'],
|
|
514
541
|
max_coverage=self.max_coverage,
|
|
515
542
|
max_particles=self.max_particles,
|
|
516
543
|
export_outputpath=self.export_outputpath,
|
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
name = "PyOPIA"
|
|
3
3
|
version = "0"
|
|
4
4
|
description = "A Python Ocean Particle Image Analysis toolbox."
|
|
5
|
-
authors = [
|
|
5
|
+
authors = [
|
|
6
|
+
"Emlyn Davies <emlyn.davies@sintef.no>",
|
|
7
|
+
"Alex Nimmo Smith@plymouth.ac.uk <alex.nimmo.smith@plymouth.ac.uk>"
|
|
8
|
+
]
|
|
6
9
|
readme = "README.md"
|
|
10
|
+
repository = "https://github.com/sintef/pyopia"
|
|
11
|
+
documentation = "https://pyopia.readthedocs.io"
|
|
12
|
+
keywords = ["Ocean", "Particles", "Imaging", "Measurement", "Size distribution"]
|
|
7
13
|
packages = [{include = "pyopia"}]
|
|
8
14
|
|
|
9
15
|
[tool.poetry.dependencies]
|
|
@@ -35,9 +41,16 @@ xarray = "^2023.8.0"
|
|
|
35
41
|
typer = {extras = ["all"], version = "^0.9.0"}
|
|
36
42
|
pandas = {version = "^2.1.1", extras = ["computation"]}
|
|
37
43
|
h5py = "^3.9.0"
|
|
38
|
-
tensorflow-io-gcs-filesystem = "0.31.0"
|
|
39
|
-
tensorflow-cpu = "2.11.0"
|
|
40
44
|
poetry-version-plugin = "^0.2.0"
|
|
45
|
+
tensorflow-macos = {version = "2.11.0", optional = true, markers = "sys_platform == 'darwin' and platform_machine == 'arm64'"}
|
|
46
|
+
tensorflow-cpu = {version = "2.11.0", optional = true}
|
|
47
|
+
tensorflow-io-gcs-filesystem = [
|
|
48
|
+
{version = ">=0.31.0", optional=true}
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[tool.poetry.extras]
|
|
52
|
+
classification-arm64 = ["tensorflow-io-gcs-filesystem", "tensorflow-macos"]
|
|
53
|
+
classification = ["tensorflow-io-gcs-filesystem", "tensorflow-cpu"]
|
|
41
54
|
|
|
42
55
|
[tool.poetry-version-plugin]
|
|
43
56
|
source = "init"
|
pyopia-1.0.0/pyopia/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '1.0.0'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|