from __future__ import annotations
import json
import os
import warnings
from pathlib import Path
from typing import Union
import numpy as np
import tifffile
from PyLorentz.utils.utils import norm_image
[docs]
def write_tif(
data: np.ndarray,
path: os.PathLike,
scale: float,
v: float = 1,
unit: str = "nm",
overwrite: bool = True,
color: bool = False,
):
"""
scale in nm/pixel default,
saves as float32 if greyscale, or uint8 if color image
"""
if scale is not None:
res = 1 / scale
else:
res = 0
if not overwrite:
path = overwrite_rename(path)
if v >= 1:
print("Saving tif: ", path)
if color:
im = (255 * norm_image(data)).astype(np.uint8)
else:
if np.ndim(data) == 3:
if np.shape(data)[0] in [3, 4]:
warnings.warn("If this is a color image, save with color=True")
im = data.astype(np.float32)
tifffile.imwrite(
path,
im,
imagej=True,
resolution=(res, res),
metadata={"unit": unit},
)
return
save_tif = write_tif # alias
write_tiff = write_tif # alias
[docs]
def overwrite_rename(filepath: os.PathLike | str, spacer: str = "_", incr_number: bool = True):
"""Given a filepath, check if file exists already. If so, add numeral 1 to end,
if already ends with a numeral increment by 1.
Args:
filepath (str): filepath to be checked
Returns:
Path: [description]
"""
file_str = str(filepath)
file, ext = os.path.splitext(file_str)
if os.path.isfile(file_str):
if file[-1].isnumeric() and incr_number:
file, num = splitnum(file)
nname = file + str(int(num) + 1) + ext
return overwrite_rename(nname)
else:
return overwrite_rename(file + spacer + "1" + ext, incr_number=True)
else:
return Path(file_str)
[docs]
def overwrite_rename_dir(dirpath: os.PathLike, spacer: str = "_v"):
"""Given a filepath, check if file exists already. If so, add numeral 1 to end,
if already ends with a numeral increment by 1.
Args:
filepath (str): filepath to be checked
Returns:
str: [description]
"""
dirpath = Path(dirpath)
if dirpath.is_dir():
if not any(dirpath.iterdir()): # directory is empty
return dirpath
dirname = dirpath.stem
if dirname[-1].isnumeric(): # TODO add check for if is date format
splits = dirname.split(spacer)
if len(splits) > 1:
name = spacer.join(splits[:-1])
num = int(splitnum(splits[-1])[-1])
new_num = name + spacer + str(num + 1) + "/"
return overwrite_rename_dir(dirpath.parents[0] / new_num)
else:
return overwrite_rename_dir(dirpath.parents[0] / (dirname + spacer + "1/"))
else:
return overwrite_rename_dir(dirpath.parents[0] / (dirname + spacer + "1/"))
else:
return dirpath
[docs]
def splitnum(s: str):
"""split the trailing number off a string. Returns (stripped_string, number)"""
head = s.rstrip("-.0123456789")
tail = s[len(head) :]
return head, tail
[docs]
def prep_dict_for_json(d: dict):
"""
still plenty of things it doesn't handle
"""
def _json_serializable(val):
if isinstance(val, np.ndarray):
return val.tolist()
elif isinstance(val, np.generic):
return val.item()
elif isinstance(val, Path):
return str(val)
elif isinstance(val, list):
for i in range(len(val)):
val[i] = _json_serializable(val[i])
return val
elif isinstance(val, dict): #
return prep_dict_for_json(val)
# elif: ## as things come up will need to add
else:
return val
for key, val in d.items():
d[key] = _json_serializable(val)
return d
[docs]
def write_json(d: dict, path: os.PathLike, overwrite: bool = True, v: int = 1):
path = Path(path)
d2 = prep_dict_for_json(d.copy())
if not path.suffix.lower() in [".json", ".txt"]:
path = path.parent / (path.name + ".json")
if path.exists() and not overwrite:
path = overwrite_rename(path)
if v >= 1:
print(f"Saving json: {path}")
# for key, val in d2.items():
# print(f"key: {key} | type {type(val)} ")
with open(path, "w", encoding="utf-8") as f:
json.dump(d2, f, ensure_ascii=False, indent=4, sort_keys=True)
return