forked from napari/napari-metadata
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfile_size.py
More file actions
96 lines (82 loc) · 2.71 KB
/
Copy pathfile_size.py
File metadata and controls
96 lines (82 loc) · 2.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
"""The file size portion of the metadata widget is not part of the
metadata stored with the image (e.g. name, scale). Instead, it is
a property which is populated on the fly at runtime.
"""
import logging
import math
import urllib
from pathlib import Path
from typing import Union
from napari.layers import Layer
logger = logging.getLogger()
def _generate_text_for_size(size: Union[int, float], suffix: str = '') -> str:
"""Generate the text for the file size widget. Consumes size in bytes,
reduces the order of magnitude and appends the units. Optionally adds
an addition suffix to the end of the string.
>>> generate_text_for_size(13)
'13.00 bytes'
>>> generate_text_for_size(1303131, suffix=' (in memory)')
'1.30 MB (in memory)'
Parameters
---------
size: (int | float)
The size in bytes
suffix: (str, optional)
Addition text suffix to add to the display. Defaults to ''.
Returns
-------
str
formatted text string for the file size
"""
order = 0 if size == 0 else int(math.log10(size))
logger.debug('order: %s', order)
if order <= 2:
text = f'{size:.2f} bytes'
elif order >= 3 and order < 6:
text = f'{size / (10**3):.2f} KB'
elif order >= 6 and order < 9:
text = f'{size / 10**6:.2f} MB'
else:
text = f'{size / 10**9:.2f} GB'
return f'{text}{suffix}'
def generate_display_size(layer: Layer) -> str:
"""High level generator for the displayed file size text on the widget.
If the provided layer has a source path, it will read the memory size on
disk. If there is no source path on the layer, it will use the size of
the data array.
Parameters
----------
layer: napari.Layer
Napari Layer for which to generate file size text
Returns
-------
str
Formatted string for the file size or size in memory of the data.
"""
is_url = urllib.parse.urlparse(layer.source.path).scheme in (
'http',
'https',
)
# data exists in file on disk
if layer.source.path and not is_url:
p = Path(layer.source.path)
if p.is_dir():
size = sum(
file.stat().st_size for file in p.rglob('*') if file.is_file()
)
else:
size = p.stat().st_size
suffix = ''
# data exists only in memory
else:
if (
type(layer).__name__ == 'Shapes'
or type(layer).__name__ == 'Surface'
or layer.multiscale is True
):
size = sum(d.nbytes for d in layer.data)
else:
size = layer.data.nbytes
suffix = ' (in memory)'
text = _generate_text_for_size(size, suffix=suffix)
return text