micress-micpy 0.2.13b4__py3-none-any.whl → 0.2.15b0__py3-none-any.whl
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.
- micpy/bin.py +95 -93
- micpy/utils.py +9 -6
- micpy/version.py +1 -1
- {micress_micpy-0.2.13b4.dist-info → micress_micpy-0.2.15b0.dist-info}/METADATA +2 -1
- micress_micpy-0.2.15b0.dist-info/RECORD +12 -0
- micress_micpy-0.2.13b4.dist-info/RECORD +0 -12
- {micress_micpy-0.2.13b4.dist-info → micress_micpy-0.2.15b0.dist-info}/LICENSE +0 -0
- {micress_micpy-0.2.13b4.dist-info → micress_micpy-0.2.15b0.dist-info}/WHEEL +0 -0
- {micress_micpy-0.2.13b4.dist-info → micress_micpy-0.2.15b0.dist-info}/top_level.txt +0 -0
micpy/bin.py
CHANGED
|
@@ -5,6 +5,7 @@ from typing import Callable, IO, List, Tuple, Generator
|
|
|
5
5
|
|
|
6
6
|
import gzip
|
|
7
7
|
import os
|
|
8
|
+
import sys
|
|
8
9
|
import warnings
|
|
9
10
|
import zlib
|
|
10
11
|
|
|
@@ -230,7 +231,7 @@ class Index(List[Position]):
|
|
|
230
231
|
@staticmethod
|
|
231
232
|
def from_file(
|
|
232
233
|
file: IO[bytes],
|
|
233
|
-
|
|
234
|
+
verbose: bool = True,
|
|
234
235
|
chunk_size: int = Chunk.DEFAULT_SIZE,
|
|
235
236
|
compressed: bool = True,
|
|
236
237
|
position: Position = None,
|
|
@@ -240,7 +241,7 @@ class Index(List[Position]):
|
|
|
240
241
|
file, chunk_size=chunk_size, compressed=compressed, position=position
|
|
241
242
|
)
|
|
242
243
|
|
|
243
|
-
if
|
|
244
|
+
if verbose:
|
|
244
245
|
iterator = utils.progress_indicator(
|
|
245
246
|
iterator, description="Indexing", unit="Field"
|
|
246
247
|
)
|
|
@@ -250,13 +251,13 @@ class Index(List[Position]):
|
|
|
250
251
|
@staticmethod
|
|
251
252
|
def from_filename(
|
|
252
253
|
filename: str,
|
|
253
|
-
|
|
254
|
+
verbose: bool = True,
|
|
254
255
|
chunk_size: int = Chunk.DEFAULT_SIZE,
|
|
255
256
|
compressed: bool = True,
|
|
256
257
|
):
|
|
257
258
|
"""Build an index from a binary file."""
|
|
258
259
|
file = open(filename, "rb")
|
|
259
|
-
return Index.from_file(file,
|
|
260
|
+
return Index.from_file(file, verbose, chunk_size, compressed)
|
|
260
261
|
|
|
261
262
|
|
|
262
263
|
class Field(np.ndarray):
|
|
@@ -535,7 +536,7 @@ class FieldList(List[Field]):
|
|
|
535
536
|
raise ImportError("matplotlib is not installed")
|
|
536
537
|
|
|
537
538
|
if cols is None:
|
|
538
|
-
cols = int(np.sqrt(len(self)))
|
|
539
|
+
cols = int(np.ceil(np.sqrt(len(self))))
|
|
539
540
|
|
|
540
541
|
rows = (len(self) + cols - 1) // cols
|
|
541
542
|
|
|
@@ -576,12 +577,14 @@ class File:
|
|
|
576
577
|
self,
|
|
577
578
|
filename: str,
|
|
578
579
|
chunk_size: int = Chunk.DEFAULT_SIZE,
|
|
580
|
+
verbose: bool = True,
|
|
579
581
|
):
|
|
580
582
|
"""Initialize a binary file.
|
|
581
583
|
|
|
582
584
|
Args:
|
|
583
585
|
filename (str): File name.
|
|
584
586
|
chunk_size (int, optional): Chunk size in bytes. Defaults to 8388608 (8 MiB).
|
|
587
|
+
verbose (bool, optional): Verbose output. Defaults to True.
|
|
585
588
|
|
|
586
589
|
Raises:
|
|
587
590
|
FileNotFoundError: If file is not found.
|
|
@@ -589,8 +592,9 @@ class File:
|
|
|
589
592
|
if not os.path.isfile(filename):
|
|
590
593
|
raise FileNotFoundError(f"File not found: {filename}")
|
|
591
594
|
|
|
592
|
-
self._filename = filename
|
|
595
|
+
self._filename: str = filename
|
|
593
596
|
self._chunk_size: int = chunk_size
|
|
597
|
+
self._verbose: bool = verbose
|
|
594
598
|
|
|
595
599
|
self._file: IO[bytes] = None
|
|
596
600
|
self._compressed: bool = None
|
|
@@ -604,11 +608,8 @@ class File:
|
|
|
604
608
|
try:
|
|
605
609
|
self.find_geo()
|
|
606
610
|
except (geo.GeometryFileNotFoundError, geo.MultipleGeometryFilesError):
|
|
607
|
-
|
|
608
|
-
"Caution: A geometry file was not found.
|
|
609
|
-
"To read a geometry from a designated location, use the read_geo() method. "
|
|
610
|
-
"Alternatively, you can manually set the geometry by executing set_geo()."
|
|
611
|
-
)
|
|
611
|
+
if self._verbose:
|
|
612
|
+
self._warn("Caution: A geometry file was not found.")
|
|
612
613
|
|
|
613
614
|
def __getitem__(self, key: int or slice or list or Callable[[Field], bool]):
|
|
614
615
|
return self.read(key)
|
|
@@ -622,73 +623,75 @@ class File:
|
|
|
622
623
|
def __iter__(self):
|
|
623
624
|
return self.iterate()
|
|
624
625
|
|
|
625
|
-
def
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
self._file = open(self._filename, "rb")
|
|
629
|
-
self._compressed = utils.is_compressed(self._filename)
|
|
626
|
+
def _info(self, *args):
|
|
627
|
+
if self._verbose:
|
|
628
|
+
print(*args)
|
|
630
629
|
|
|
631
|
-
|
|
630
|
+
def _warn(self, *args):
|
|
631
|
+
if self._verbose:
|
|
632
|
+
print(*args, file=sys.stderr)
|
|
632
633
|
|
|
633
|
-
def
|
|
634
|
-
|
|
634
|
+
def _open_file(self):
|
|
635
|
+
self._file = open(self._filename, "rb")
|
|
636
|
+
self._compressed = utils.is_compressed(self._filename)
|
|
637
|
+
|
|
638
|
+
def _close_file(self):
|
|
635
639
|
if self._file:
|
|
636
640
|
self._file.close()
|
|
641
|
+
self._reset()
|
|
637
642
|
|
|
643
|
+
def _reset(self):
|
|
638
644
|
self._file = None
|
|
639
645
|
self._compressed = None
|
|
640
646
|
self._created = None
|
|
641
647
|
self._modified = None
|
|
642
648
|
self._index = None
|
|
643
649
|
|
|
644
|
-
def
|
|
645
|
-
self
|
|
646
|
-
|
|
647
|
-
create: bool = None,
|
|
648
|
-
update: bool = None,
|
|
649
|
-
) -> Index:
|
|
650
|
-
"""Build an index of the file.
|
|
651
|
-
|
|
652
|
-
Args:
|
|
653
|
-
show_progress (bool, optional): Show progress bar. Defaults to True.
|
|
654
|
-
create (bool, optional): Create the index. Defaults to None (auto).
|
|
655
|
-
update (bool, optional): Update the index. Defaults to None (auto).
|
|
650
|
+
def _update_timestamps(self):
|
|
651
|
+
self._created = os.path.getctime(self._filename)
|
|
652
|
+
self._modified = os.path.getmtime(self._filename)
|
|
656
653
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
return self._created != os.path.getctime(self._filename)
|
|
663
|
-
|
|
664
|
-
def file_modified():
|
|
665
|
-
return self._modified != os.path.getmtime(self._filename)
|
|
666
|
-
|
|
667
|
-
create = create if create is not None else file_created()
|
|
668
|
-
update = update if update is not None else file_modified()
|
|
669
|
-
|
|
670
|
-
if create:
|
|
671
|
-
self.close()
|
|
672
|
-
self.open()
|
|
654
|
+
def open(self):
|
|
655
|
+
"""Open the file."""
|
|
656
|
+
if not self._file:
|
|
657
|
+
self.create_index()
|
|
658
|
+
return self
|
|
673
659
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
660
|
+
def close(self):
|
|
661
|
+
"""Close the file."""
|
|
662
|
+
self._close_file()
|
|
663
|
+
|
|
664
|
+
def index(self):
|
|
665
|
+
"""Get the index of the file."""
|
|
666
|
+
if self._created != os.path.getctime(self._filename):
|
|
667
|
+
self.create_index()
|
|
668
|
+
elif self._modified != os.path.getmtime(self._filename):
|
|
669
|
+
self.update_index()
|
|
670
|
+
return self._index
|
|
677
671
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
672
|
+
def create_index(self):
|
|
673
|
+
"""Create an index of the file."""
|
|
674
|
+
self._close_file()
|
|
675
|
+
self._open_file()
|
|
676
|
+
self._update_timestamps()
|
|
677
|
+
self._index = Index.from_file(
|
|
678
|
+
self._file,
|
|
679
|
+
verbose=self._verbose,
|
|
681
680
|
chunk_size=self._chunk_size,
|
|
682
|
-
|
|
681
|
+
compressed=self._compressed,
|
|
683
682
|
)
|
|
684
683
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
self.
|
|
690
|
-
|
|
691
|
-
|
|
684
|
+
def update_index(self):
|
|
685
|
+
"""Update the index of the file."""
|
|
686
|
+
self._update_timestamps()
|
|
687
|
+
index = Index.from_file(
|
|
688
|
+
self._file,
|
|
689
|
+
verbose=self._verbose,
|
|
690
|
+
chunk_size=self._chunk_size,
|
|
691
|
+
compressed=self._compressed,
|
|
692
|
+
position=self._index[-1],
|
|
693
|
+
)
|
|
694
|
+
self._index.extend(index)
|
|
692
695
|
|
|
693
696
|
def times(self) -> List[float]:
|
|
694
697
|
"""Get the times of the fields in the file.
|
|
@@ -748,7 +751,7 @@ class File:
|
|
|
748
751
|
"""Get a string representation of the geometry."""
|
|
749
752
|
|
|
750
753
|
if self.shape is None or self.spacing is None:
|
|
751
|
-
|
|
754
|
+
self._info("Geometry: None")
|
|
752
755
|
return
|
|
753
756
|
|
|
754
757
|
dimensions = Field.dimensions(self.shape)
|
|
@@ -756,58 +759,57 @@ class File:
|
|
|
756
759
|
spacing = np.round(self.spacing, 7)
|
|
757
760
|
size = cells * spacing
|
|
758
761
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
f"Grid Spacing (Cell Size): {tuple(spacing)}μm³"
|
|
764
|
-
)
|
|
762
|
+
self._info(f"Geometry: {dimensions}-Dimensional Grid")
|
|
763
|
+
self._info(f"Grid Size: {tuple(size)}μm³")
|
|
764
|
+
self._info(f"Grid Shape (Cell Count): {tuple(cells)}")
|
|
765
|
+
self._info(f"Grid Spacing (Cell Size): {tuple(spacing)}μm³")
|
|
765
766
|
|
|
766
|
-
def iterate(self
|
|
767
|
+
def iterate(self):
|
|
767
768
|
"""Iterate over fields in the file.
|
|
768
769
|
|
|
769
|
-
Args:
|
|
770
|
-
show_progress (bool, optional): Show progress bar. Defaults to True.
|
|
771
|
-
|
|
772
770
|
Returns:
|
|
773
771
|
Field: Field data.
|
|
774
772
|
"""
|
|
775
|
-
for position in self.index(
|
|
773
|
+
for position in self.index():
|
|
776
774
|
yield Field.read(position, shape=self.shape, spacing=self.spacing)
|
|
777
775
|
|
|
778
|
-
def read(
|
|
779
|
-
self,
|
|
780
|
-
key: int or slice or list or Callable[[Field], bool] = None,
|
|
781
|
-
show_progress: bool = True,
|
|
782
|
-
):
|
|
776
|
+
def read(self, key: int or slice or list or Callable[[Field], bool] = None):
|
|
783
777
|
"""Read a field from the file.
|
|
784
778
|
|
|
785
779
|
Args:
|
|
786
780
|
key (int or list or slice or Callable[[Field], bool], optional): Field ID,
|
|
787
781
|
list of field IDs, a slice object, or a condition function.
|
|
788
782
|
Defaults to None.
|
|
789
|
-
show_progress (bool, optional): Show progress bar. Defaults to True.
|
|
790
783
|
|
|
791
784
|
Returns:
|
|
792
|
-
|
|
785
|
+
FieldList: List of fields.
|
|
793
786
|
"""
|
|
794
787
|
|
|
795
788
|
def read_field(self, field_id: int or slice or list):
|
|
796
789
|
position = self._index[field_id]
|
|
797
790
|
return Field.read(position, shape=self.shape, spacing=self.spacing)
|
|
798
791
|
|
|
799
|
-
|
|
792
|
+
def iterable(iterable):
|
|
793
|
+
if self._verbose:
|
|
794
|
+
return utils.progress_indicator(
|
|
795
|
+
iterable, description="Reading", unit="Field"
|
|
796
|
+
)
|
|
797
|
+
return iterable
|
|
798
|
+
|
|
799
|
+
self.index()
|
|
800
800
|
|
|
801
801
|
if key is None:
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
802
|
+
fields = list(field for field in iterable(self.iterate()))
|
|
803
|
+
elif isinstance(key, int):
|
|
804
|
+
fields = [read_field(self, key)]
|
|
805
|
+
elif isinstance(key, slice):
|
|
806
|
+
indices = range(*key.indices(len(self._index)))
|
|
807
|
+
fields = [read_field(self, i) for i in iterable(indices)]
|
|
808
|
+
elif isinstance(key, list):
|
|
809
|
+
fields = [read_field(self, i) for i in iterable(key)]
|
|
810
|
+
elif isinstance(key, Callable):
|
|
811
|
+
fields = [field for field in iterable(self.iterate()) if key(field)]
|
|
812
|
+
else:
|
|
813
|
+
raise TypeError("Invalid argument type")
|
|
814
|
+
|
|
815
|
+
return FieldList(fields)
|
micpy/utils.py
CHANGED
|
@@ -8,19 +8,22 @@ def progress_indicator(iterable, description="Progress", unit="Iteration", start
|
|
|
8
8
|
"""Progress indicator for iterable."""
|
|
9
9
|
|
|
10
10
|
start_time = time.time()
|
|
11
|
+
|
|
11
12
|
for i, item in enumerate(iterable, start=start):
|
|
12
13
|
yield item
|
|
14
|
+
|
|
13
15
|
elapsed_time = time.time() - start_time
|
|
14
16
|
average_time = elapsed_time / i
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
)
|
|
20
|
-
# The print method's flush is not guaranteed to work in IPython environments. A
|
|
21
|
-
# workaround is to use sys.stdout.flush() instead.
|
|
18
|
+
message = f"\r{description}: {unit} {i}. Elapsed Time: {elapsed_time:.2f}s. Average Time/{unit}: {average_time:.2f}s"
|
|
19
|
+
|
|
20
|
+
sys.stdout.write("\r\x1b[0K") # Clear line
|
|
21
|
+
print(message, end="")
|
|
22
22
|
sys.stdout.flush()
|
|
23
23
|
|
|
24
|
+
print("")
|
|
25
|
+
sys.stdout.flush()
|
|
26
|
+
|
|
24
27
|
|
|
25
28
|
def is_compressed(filename):
|
|
26
29
|
"""Check if a file is compressed."""
|
micpy/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.2.
|
|
1
|
+
__version__ = "0.2.15b0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: micress-micpy
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.15b0
|
|
4
4
|
Summary: MicPy is a Python package to facilitate MICRESS workflows.
|
|
5
5
|
Author: Lukas Koschmieder
|
|
6
6
|
Author-email: l.koschmieder@access-technology.de
|
|
@@ -59,6 +59,7 @@ for field in bin.File("A001_Delta_Gamma.conc1"):
|
|
|
59
59
|
#### Read all fields
|
|
60
60
|
|
|
61
61
|
```python
|
|
62
|
+
|
|
62
63
|
from micpy import bin
|
|
63
64
|
|
|
64
65
|
with bin.File("A001_Delta_Gamma.conc1") as file:
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
micpy/__init__.py,sha256=7wQUaseppjQYZW1iAVNm2WSDjvBLlqtY8tiHsfDaW5Q,148
|
|
2
|
+
micpy/bin.py,sha256=0RB4FTad00sriZvQdHuTvkzT9D4_pLS_eFwpYS7EOhA,26492
|
|
3
|
+
micpy/geo.py,sha256=dcXcxvAxPpe4Rrs1ImYs8H67c2228brabdefJMoLn0g,7354
|
|
4
|
+
micpy/matplotlib.py,sha256=toxFTtTaA-usuWUltMp0XufQee4-n68XH7SN2In2NZY,1845
|
|
5
|
+
micpy/tab.py,sha256=ZXhL6bg17W3jqFFX28htCOAV9W_W3op_-GD7iU5a_wY,3547
|
|
6
|
+
micpy/utils.py,sha256=Kt1AvhMvWer9uftbb88X7N27aXtQdJl26grHmmm2vOQ,859
|
|
7
|
+
micpy/version.py,sha256=tyiEmp3lrfZHINaXvAGtz6wbg_fRgizg1D1jsMt3PXo,26
|
|
8
|
+
micress_micpy-0.2.15b0.dist-info/LICENSE,sha256=seHdCiArizUoWZ6bEFg6N3K2ZtfPK35wvOwg0kH-f6o,1488
|
|
9
|
+
micress_micpy-0.2.15b0.dist-info/METADATA,sha256=Po-1cfNOIsV2m9wU_oj8kKzf2LllWQf-50PQD5O_g3c,3824
|
|
10
|
+
micress_micpy-0.2.15b0.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
11
|
+
micress_micpy-0.2.15b0.dist-info/top_level.txt,sha256=RiopkpW0AGNYdtOW2eQUWgm3yHGC13q9pWlHb2alhiE,6
|
|
12
|
+
micress_micpy-0.2.15b0.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
micpy/__init__.py,sha256=7wQUaseppjQYZW1iAVNm2WSDjvBLlqtY8tiHsfDaW5Q,148
|
|
2
|
-
micpy/bin.py,sha256=k75S6izFjBmNohjjHm-DEOSYp5eCl_iWi_bs-4OFjlc,26530
|
|
3
|
-
micpy/geo.py,sha256=dcXcxvAxPpe4Rrs1ImYs8H67c2228brabdefJMoLn0g,7354
|
|
4
|
-
micpy/matplotlib.py,sha256=toxFTtTaA-usuWUltMp0XufQee4-n68XH7SN2In2NZY,1845
|
|
5
|
-
micpy/tab.py,sha256=ZXhL6bg17W3jqFFX28htCOAV9W_W3op_-GD7iU5a_wY,3547
|
|
6
|
-
micpy/utils.py,sha256=fN2FFRlhOnAe00fdrdGBJvhlPrfqIyIiWK9PY7HQaHQ,919
|
|
7
|
-
micpy/version.py,sha256=4G2XnZ6DntBZ0cJueBhEVZgO2A-1Auou_W5b-24qWKk,26
|
|
8
|
-
micress_micpy-0.2.13b4.dist-info/LICENSE,sha256=seHdCiArizUoWZ6bEFg6N3K2ZtfPK35wvOwg0kH-f6o,1488
|
|
9
|
-
micress_micpy-0.2.13b4.dist-info/METADATA,sha256=7-5BHF15NtEdkxp8pO5Wj6JtAcj3P0TRR_-DfOQB_Q8,3822
|
|
10
|
-
micress_micpy-0.2.13b4.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
11
|
-
micress_micpy-0.2.13b4.dist-info/top_level.txt,sha256=RiopkpW0AGNYdtOW2eQUWgm3yHGC13q9pWlHb2alhiE,6
|
|
12
|
-
micress_micpy-0.2.13b4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|