Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
qim3d
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
QIM
Tools
qim3d
Commits
fa52d4cd
Commit
fa52d4cd
authored
1 year ago
by
s184058
Committed by
fima
1 year ago
Browse files
Options
Downloads
Patches
Plain Diff
First version of save function + unit tests
parent
a522289b
No related branches found
No related tags found
1 merge request
!24
First version of save function + unit tests
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
qim3d/io/__init__.py
+1
-1
1 addition, 1 deletion
qim3d/io/__init__.py
qim3d/io/save.py
+101
-5
101 additions, 5 deletions
qim3d/io/save.py
qim3d/tests/io/test_save.py
+166
-0
166 additions, 0 deletions
qim3d/tests/io/test_save.py
with
268 additions
and
6 deletions
qim3d/io/__init__.py
+
1
−
1
View file @
fa52d4cd
from
.downloader
import
Downloader
from
.load
import
DataLoader
,
load
,
ImgExamples
from
.save
import
save
from
.save
import
DataSaver
,
save
from
.sync
import
Sync
from
.
import
logger
\ No newline at end of file
This diff is collapsed.
Click to expand it.
qim3d/io/save.py
+
101
−
5
View file @
fa52d4cd
"""
Provides functionality for saving data to various file formats.
"""
import
os
import
tifffile
import
numpy
as
np
from
qim3d.io.logger
import
log
class
DataSaver
:
def
__init__
(
self
):
self
.
verbose
=
False
"""
Utility class for saving data to different file formats.
Attributes:
replace (bool): Specifies if an existing file with identical path is replaced.
compression (bool): Specifies if the file is with Deflate compression.
Methods:
save_tiff(path,data): Save data to a TIFF file to the given path.
load(path,data): Save data to the given path.
Example:
image = qim3d.examples.blobs_256x256
saver = qim3d.io.DataSaver(compression=True)
saver.save_tiff(
"
image.tif
"
,image)
"""
def
__init__
(
self
,
**
kwargs
):
"""
Initializes a new instance of the DataSaver class.
Args:
replace (bool, optional): Specifies if an existing file with identical path should be replaced.
Default is False.
compression (bool, optional): Specifies if the file should be saved with Deflate compression.
Default is False.
"""
self
.
replace
=
kwargs
.
get
(
"
replace
"
,
False
)
self
.
compression
=
kwargs
.
get
(
"
compression
"
,
False
)
def
save_tiff
(
self
,
path
,
data
):
"""
Save data to a TIFF file to the given path.
Args:
path (str): The path to save file to
data (numpy.ndarray): The data to be saved
"""
tifffile
.
imwrite
(
path
,
data
,
compression
=
self
.
compression
)
def
save
(
self
,
path
,
data
):
raise
NotImplementedError
(
"
Save is not implemented yet
"
)
"""
Save data to the given path.
Args:
path (str): The path to save file to
data (numpy.ndarray): The data to be saved
Raises:
ValueError: If the file format is not supported.
ValueError: If the specified folder does not exist.
ValueError: If a file extension is not provided.
ValueError: if a file with the specified path already exists and replace=False.
Example:
image = qim3d.examples.blobs_256x256
saver = qim3d.io.DataSaver(compression=True)
saver.save(
"
image.tif
"
,image)
"""
folder
=
os
.
path
.
dirname
(
path
)
or
'
.
'
# Check if directory exists
if
os
.
path
.
isdir
(
folder
):
_
,
ext
=
os
.
path
.
splitext
(
path
)
# Check if provided path contains file extension
if
ext
:
# Check if a file with the given path already exists
if
os
.
path
.
isfile
(
path
)
and
not
self
.
replace
:
raise
ValueError
(
"
A file with the provided path already exists. To replace it set
'
replace=True
'"
)
if
path
.
endswith
((
"
.tif
"
,
"
.tiff
"
)):
return
self
.
save_tiff
(
path
,
data
)
else
:
raise
ValueError
(
"
Unsupported file format
"
)
else
:
raise
ValueError
(
'
Please provide a file extension
'
)
else
:
raise
ValueError
(
f
'
The directory
{
folder
}
does not exist. Please provide a valid directory
'
)
def
save
(
path
,
data
,
replace
=
False
,
compression
=
False
,
**
kwargs
):
"""
Save data to a specified file path.
Args:
path (str): The path to save file to
data (numpy.ndarray): The data to be saved
replace (bool, optional): Specifies if an existing file with identical path should be replaced.
Default is False.
compression (bool, optional): Specifies if the file should be saved with Deflate compression (lossless).
Default is False.
**kwargs: Additional keyword arguments to be passed to the DataSaver constructor
Example:
image = qim3d.examples.blobs_256x256
qim3d.io.save(
"
image.tif
"
,image,compression=True)
"""
def
save
(
path
,
data
):
return
DataSaver
().
save
(
path
,
data
)
DataSaver
(
replace
=
replace
,
compression
=
compression
,
**
kwargs
).
save
(
path
,
data
)
\ No newline at end of file
This diff is collapsed.
Click to expand it.
qim3d/tests/io/test_save.py
0 → 100644
+
166
−
0
View file @
fa52d4cd
import
qim3d
import
tempfile
import
numpy
as
np
import
os
import
hashlib
import
pytest
def
test_image_exist
():
# Create random test image
test_image
=
np
.
random
.
randint
(
0
,
256
,(
100
,
100
,
100
),
'
uint8
'
)
# Create temporary directory
with
tempfile
.
TemporaryDirectory
()
as
temp_dir
:
image_path
=
os
.
path
.
join
(
temp_dir
,
"
test_image.tif
"
)
# Save to temporary directory
qim3d
.
io
.
save
(
image_path
,
test_image
)
# Assert that test image has been saved
assert
os
.
path
.
exists
(
image_path
)
def
test_compression
():
# Get test image (should not be random in order for compression to function)
test_image
=
qim3d
.
examples
.
blobs_256x256
# Create temporary directory
with
tempfile
.
TemporaryDirectory
()
as
temp_dir
:
image_path
=
os
.
path
.
join
(
temp_dir
,
"
test_image.tif
"
)
compressed_image_path
=
os
.
path
.
join
(
temp_dir
,
"
compressed_test_image.tif
"
)
# Save to temporary directory with and without compression
qim3d
.
io
.
save
(
image_path
,
test_image
)
qim3d
.
io
.
save
(
compressed_image_path
,
test_image
,
compression
=
True
)
# Compute file sizes
file_size
=
os
.
path
.
getsize
(
image_path
)
compressed_file_size
=
os
.
path
.
getsize
(
compressed_image_path
)
# Assert that compressed file size is smaller than non-compressed file size
assert
compressed_file_size
<
file_size
def
test_image_matching
():
# Create random test image
original_image
=
np
.
random
.
randint
(
0
,
256
,(
100
,
100
,
100
),
'
uint8
'
)
# Create temporary directory
with
tempfile
.
TemporaryDirectory
()
as
temp_dir
:
image_path
=
os
.
path
.
join
(
temp_dir
,
"
original_image.tif
"
)
# Save to temporary directory
qim3d
.
io
.
save
(
image_path
,
original_image
)
# Load from temporary directory
saved_image
=
qim3d
.
io
.
load
(
image_path
)
# Get hashes
original_hash
=
calculate_image_hash
(
original_image
)
saved_hash
=
calculate_image_hash
(
saved_image
)
# Assert that original image is identical to saved_image
assert
original_hash
==
saved_hash
def
test_compressed_image_matching
():
# Get test image (should not be random in order for compression to function)
original_image
=
qim3d
.
examples
.
blobs_256x256
# Create temporary directory
with
tempfile
.
TemporaryDirectory
()
as
temp_dir
:
image_path
=
os
.
path
.
join
(
temp_dir
,
"
original_image.tif
"
)
# Save to temporary directory
qim3d
.
io
.
save
(
image_path
,
original_image
,
compression
=
True
)
# Load from temporary directory
saved_image_compressed
=
qim3d
.
io
.
load
(
image_path
)
# Get hashes
original_hash
=
calculate_image_hash
(
original_image
)
compressed_hash
=
calculate_image_hash
(
saved_image_compressed
)
# Assert that original image is identical to saved_image
assert
original_hash
==
compressed_hash
def
test_file_replace
():
# Create random test image
test_image1
=
np
.
random
.
randint
(
0
,
256
,(
100
,
100
,
100
),
'
uint8
'
)
test_image2
=
np
.
random
.
randint
(
0
,
256
,(
100
,
100
,
100
),
'
uint8
'
)
# Create temporary directory
with
tempfile
.
TemporaryDirectory
()
as
temp_dir
:
image_path
=
os
.
path
.
join
(
temp_dir
,
"
test_image.tif
"
)
# Save first test image to temporary directory
qim3d
.
io
.
save
(
image_path
,
test_image1
)
# Get hash
hash1
=
calculate_image_hash
(
qim3d
.
io
.
load
(
image_path
))
# Replace existing file
qim3d
.
io
.
save
(
image_path
,
test_image2
,
replace
=
True
)
# Get hash again
hash2
=
calculate_image_hash
(
qim3d
.
io
.
load
(
image_path
))
# Assert that the file was modified by checking if the second modification time is newer than the first
assert
hash1
!=
hash2
def
test_file_already_exists
():
# Create random test image
test_image1
=
np
.
random
.
randint
(
0
,
256
,(
100
,
100
,
100
),
'
uint8
'
)
test_image2
=
np
.
random
.
randint
(
0
,
256
,(
100
,
100
,
100
),
'
uint8
'
)
# Create temporary directory
with
tempfile
.
TemporaryDirectory
()
as
temp_dir
:
image_path
=
os
.
path
.
join
(
temp_dir
,
"
test_image.tif
"
)
# Save first test image to temporary directory
qim3d
.
io
.
save
(
image_path
,
test_image1
)
with
pytest
.
raises
(
ValueError
,
match
=
"
A file with the provided path already exists. To replace it set
'
replace=True
'"
):
# Try to save another image to the existing path
qim3d
.
io
.
save
(
image_path
,
test_image2
)
def
test_no_file_ext
():
# Create random test image
test_image
=
np
.
random
.
randint
(
0
,
256
,(
100
,
100
,
100
),
'
uint8
'
)
# Create filename without extension
filename
=
'
test_image
'
# Create temporary directory
with
tempfile
.
TemporaryDirectory
()
as
temp_dir
:
image_path
=
os
.
path
.
join
(
temp_dir
,
filename
)
with
pytest
.
raises
(
ValueError
,
match
=
'
Please provide a file extension
'
):
# Try to save the test image to a path witout file extension
qim3d
.
io
.
save
(
image_path
,
test_image
)
def
test_folder_doesnt_exist
():
# Create random test image
test_image
=
np
.
random
.
randint
(
0
,
256
,(
100
,
100
,
100
),
'
uint8
'
)
# Create invalid path
invalid_path
=
os
.
path
.
join
(
'
this
'
,
'
path
'
,
'
doesnt
'
,
'
exist.tif
'
)
with
pytest
.
raises
(
ValueError
,
match
=
f
'
The directory
{
os
.
path
.
dirname
(
invalid_path
)
}
does not exist. Please provide a valid directory
'
):
# Try to save test image to an invalid path
qim3d
.
io
.
save
(
invalid_path
,
test_image
)
def
test_unsupported_file_format
():
# Create random test image
test_image
=
np
.
random
.
randint
(
0
,
256
,(
100
,
100
,
100
),
'
uint8
'
)
# Create filename with unsupported format
filename
=
'
test_image.unsupported
'
# Create temporary directory
with
tempfile
.
TemporaryDirectory
()
as
temp_dir
:
image_path
=
os
.
path
.
join
(
temp_dir
,
filename
)
with
pytest
.
raises
(
ValueError
,
match
=
'
Unsupported file format
'
):
# Try to save test image with an unsupported file extension
qim3d
.
io
.
save
(
image_path
,
test_image
)
def
calculate_image_hash
(
image
):
image_bytes
=
image
.
tobytes
()
hash_object
=
hashlib
.
md5
(
image_bytes
)
return
hash_object
.
hexdigest
()
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment