Last active
June 30, 2021 14:23
-
-
Save glyg/1ca89c3b2fe948aa8b1680aa61ec3a51 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
from pathlib import Path | |
sys.path.append(r"C:\Users\endo\Documents\endo-py") | |
import numpy as np | |
import matplotlib.pyplot as plt | |
from skimage.filters.rank import geometric_mean | |
from skimage.morphology import disk | |
from skimage.util import img_as_ubyte, img_as_uint | |
from scipy.signal import convolve2d | |
from endoscope.hw.imagecalculator import ImageCalculator | |
from endoscope.hw.waveform import Waveform | |
import tifffile | |
def get_calculator(calibration_dir, imgsize=385, **kwargs): | |
"""Instanciates an ImageCalculator from a calibration directory""" | |
npys = list(Path(calibration_dir).glob("*.npy")) | |
# take all the calibration npys and put them in a (10, num_samples) array | |
xpos = np.concatenate( | |
[np.load(npy, allow_pickle=True)[()]["xpos"] for npy in npys] | |
).reshape((len(npys), -1)) | |
ypos = np.concatenate( | |
[np.load(npy, allow_pickle=True)[()]["ypos"] for npy in npys] | |
).reshape((len(npys), -1)) | |
calculator = ImageCalculator(imgsize=imgsize, **kwargs) | |
# average positions over all the calibration data | |
calculator.xvolts = xpos.mean(axis=0) | |
calculator.yvolts = ypos.mean(axis=0) | |
return calculator | |
def npy_to_tiff(npy_file, calculator, fill_radius=5, fov=120, to_csv=True, data_srce='PMT1'): | |
"""Uses an ImageCalculator instance to compute an image | |
from an npy file, and saves the result as tiff. | |
The `fov` value determines the registered pixel size | |
""" | |
intensity = np.load(npy_file, allow_pickle=True)[()][data_srce] | |
image = calculator.calc_image(intensity) | |
if to_csv: | |
csv_fname = Path(npy_file).absolute().with_suffix(".csv") | |
with open(csv_fname, 'w', encoding='utf-8') as csvf: | |
data = np.array([calculator.xv, calculator.yv, calculator._intensities]).T | |
header = 'xv,yv,intensity' | |
np.savetxt(csvf, data, delimiter=',',header=header) | |
# find the non-empty pixels | |
mask = (calculator.image >= calculator._intensities.min()).astype(bool) | |
# put the signal of the empty pixels to the min of the image | |
im_min = calculator.image[mask.nonzero()].min() | |
calculator._image[(~mask).nonzero()] += im_min | |
# convert to uint8 | |
im = img_as_uint((calculator._image - im_min) / (calculator._image.max() - im_min)) | |
# take the local mean for empty pixels | |
filled = geometric_mean(im, disk(fill_radius), mask=mask) | |
# replace empty pixels with their local mean | |
corrected = np.where(mask, im, filled) | |
# corrected = image | |
pix_size = fov / corrected.shape[0] | |
tiff_fname = Path(npy_file).absolute().with_suffix(".ome.tif") | |
tifffile.imsave( | |
tiff_fname, | |
corrected, | |
ome=True, | |
metadata={"axes": "YX", "PhysicalSizeX": pix_size, "PhysicalSizeY": pix_size}, | |
) | |
print(f"saved {tiff_fname}") | |
return corrected | |
def convert_all_to_tiff( | |
npy_dir, | |
calibration_dir, | |
imgsize=200, | |
fill_radius=2, | |
fov=120, | |
to_csv=True, | |
data_srce="PMT1" | |
): | |
"""converts all the npy files in the npy_dir directory to tiff, using | |
calibration data from calibration_dir | |
""" | |
calculator = get_calculator(calibration_dir, imgsize=imgsize) | |
for npy_file in npy_dir.glob("*.npy"): | |
npy_to_tiff( | |
npy_file, | |
calculator, | |
fill_radius=fill_radius, | |
fov=fov, | |
to_csv=to_csv, | |
data_srce=data_srce | |
) | |
def plot_single(data_path, calib_path, index): | |
start = 0 | |
stop = 100_000 + start | |
#slc = slice(start, stop) | |
slc = slice(None, None) | |
calculator = get_calculator(calib_path, imgsize=200) # , timeslice=slc) | |
npy_file = list(data_path.glob("*.npy"))[index] | |
intensity = np.load(npy_file, allow_pickle=True)[()]["PMT1"] | |
image = calculator.calc_image(intensity[slc]) | |
# This plots the positions colored by intensity, | |
# should already look like an image | |
fig, ax = plt.subplots() | |
ax.scatter( | |
calculator.xv, | |
calculator.yv, | |
c=intensity[slc], | |
s=10) | |
ax.set_aspect("equal") | |
# get the filled image and save as tiff | |
corrected = npy_to_tiff(npy_file, calculator, fill_radius=2, fov=120) | |
fig, ax = plt.subplots() | |
ax.imshow(corrected) | |
plt.show() | |
calib_path= r'C:/Users/endo/EndoscopeData/Calibration/200um/10fps' | |
data_paths = [ | |
Path(r"C:\Users\endo\Desktop\Imaging\200um\10fps\souris_80mW_100µm"), | |
Path(r"C:\Users\endo\Desktop\Imaging\200um\10fps\souris1_50mW_8fps"), | |
Path(r"C:\Users\endo\Desktop\Imaging\200um\10fps\Souris1_80mW_8fps_100µm"), | |
Path(r"C:\Users\endo\Desktop\Imaging\200um\10fps\souris1_100µm_last_100mW"), | |
Path(r"C:\Users\endo\Desktop\Imaging\200um\10fps\souris1_100mW_100µm"), | |
Path(r"C:\Users\endo\Desktop\Imaging\200um\10fps\souris2_80mW"), | |
] | |
#plot_single(data_paths[0], calib_path, 10) | |
for data_path in data_paths: | |
print(f"treating {data_path}") | |
convert_all_to_tiff( | |
data_path, | |
calib_path, | |
imgsize=200, | |
fill_radius=2, | |
fov=120 | |
) | |
print(f"{data_path} done") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment