234 lines
9.1 KiB
Python
234 lines
9.1 KiB
Python
|
|
# encoding: utf8
|
|
# A Jython script with parameters.
|
|
# It is the duty of the scripting framework to harvest
|
|
# the 'name' parameter from the user, and then display
|
|
# the 'greeting' output parameter, based on its type.
|
|
from ij import IJ # pylint: disable=import-error
|
|
from ij import ImagePlus # pylint: disable=import-error
|
|
from ij.process import ByteProcessor # pylint: disable=import-error
|
|
from ij.process import ImageStatistics
|
|
from ij.plugin import ImageCalculator
|
|
from ij.plugin import ZProjector
|
|
from ij import WindowManager
|
|
from catalog import Sequence, ImageCatalog
|
|
import preprocessing
|
|
# greeting = "Hello, " + name + "!"
|
|
|
|
|
|
# image prefix :
|
|
# AF
|
|
# blé : coupes de blé
|
|
# CA : coupe d'amande
|
|
# FE : feuille d'épinard
|
|
# GGH : globule gras humain
|
|
# CRF chloroplastes de feuille d'épinard
|
|
# OL : oléosome
|
|
# DARK : dark
|
|
# white :
|
|
#
|
|
# - cin1 : cinétique 1
|
|
# phiG_40x_1 : cinétique avant et après injection enzyme gastrique
|
|
# phiG_40x_Zstack20um_1 : stack
|
|
# 0mn : on commence à enregistrer et on attend 10mn (pour le bleaching) -> phiG_40x_1
|
|
# 10mn : debut injection phase gastrique (poussée)
|
|
# 13mn : la phase gastrique (le petit tuyau contient 20ul) arrive dans la cellule d'un coup (1 nanol)
|
|
# 15mn : on arrête l'injection
|
|
# 50mn : on fait un stack -> phiG_40x_Zstack20um_1
|
|
# 51mn : début d'injection phase intestinale (poussée) -> phiG_I_40x_1
|
|
# x mn : on arrête l'injection
|
|
# 90mn : on fait un stack -> phiG_I_40x_Zstack20um_1
|
|
# - cin2 : autre échantillon similaire à cin1
|
|
# - cond[5678] : condition non réalistes
|
|
|
|
|
|
class IImageProcessingDebugger(object):
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
def on_image(self, image, image_id):
|
|
'''
|
|
:param ImagePlus image:
|
|
:param str image_id:
|
|
'''
|
|
pass
|
|
|
|
|
|
class NullDebugger(IImageProcessingDebugger):
|
|
|
|
def __init__(self):
|
|
IImageProcessingDebugger.__init__(self)
|
|
|
|
def on_image(self, image, image_id):
|
|
pass
|
|
|
|
|
|
class ImageLogger(IImageProcessingDebugger):
|
|
|
|
def __init__(self):
|
|
IImageProcessingDebugger.__init__(self)
|
|
|
|
def on_image(self, image, image_id):
|
|
# todo : WindowManager
|
|
image.show()
|
|
|
|
|
|
class Lipase(object):
|
|
|
|
def __init__(self, catalog, debugger=NullDebugger()):
|
|
'''
|
|
:param IImageProcessingDebugger im_proc_debugger:
|
|
'''
|
|
self.catalog = catalog
|
|
self.debugger = debugger
|
|
|
|
def get_image_median_value(self, src_image):
|
|
'''
|
|
:param ImagePlus src_image:
|
|
'''
|
|
# https://imagej.nih.gov/ij/developer/api/ij/process/ImageStatistics.html
|
|
stats = ImageStatistics.getStatistics(src_image.getProcessor(), ImageStatistics.MEDIAN, None)
|
|
# print(stats)
|
|
# print(stats.pixelCount)
|
|
return stats.median
|
|
|
|
def get_image_mean_value(self, src_image):
|
|
'''
|
|
:param ImagePlus src_image:
|
|
'''
|
|
# https://imagej.nih.gov/ij/developer/api/ij/process/ImageStatistics.html
|
|
stats = ImageStatistics.getStatistics(src_image.getProcessor(), ImageStatistics.MEAN, None)
|
|
# print(stats)
|
|
# print(stats.pixelCount)
|
|
return stats.mean
|
|
|
|
def test_get_image_median_value(self):
|
|
image_file_path = '/Users/graffy/ownCloud/ipr/lipase/raw-images/res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0/img_000000000_DM300_327-353_fluo_000.tif'
|
|
image = IJ.openImage(image_file_path)
|
|
median_value = self.get_image_median_value(image)
|
|
print('median value : %d' % median_value)
|
|
|
|
def find_depth_index(self, src_image, white_sequence):
|
|
''' finds in the image sequence white_sequence the image that correlates the best to src_image
|
|
|
|
:param ImagePlus src_image:
|
|
:param Sequence white_sequence:
|
|
'''
|
|
self.debugger.on_image(src_image, 'src_image')
|
|
|
|
white_sequence.open_in_imagej()
|
|
|
|
print('image type : ', src_image.getType())
|
|
src_median_value = self.get_image_median_value(src_image)
|
|
normalized_src_processor = src_image.getProcessor().convertToFloat()
|
|
normalized_src_processor.multiply(1.0 / src_median_value)
|
|
best_diff = None
|
|
best_z_index = None
|
|
for z_index in range(white_sequence.num_slices):
|
|
white_image_file_path = white_sequence.get_image_file_path(channel_index=0, frame_index=0, z_index=z_index)
|
|
white_image = IJ.openImage(white_image_file_path)
|
|
# self.debugger.on_image(white_image, 'white_image')
|
|
white_median_value = self.get_image_median_value(white_image)
|
|
# white_to_src_factor = 1.0 / float(white_median_value)
|
|
normalized_white_processor = white_image.getProcessor().convertToFloat()
|
|
normalized_white_processor.multiply(1.0 / float(white_median_value))
|
|
|
|
normalized_src = ImagePlus() # IJ.openImage("http://imagej.nih.gov/ij/images/boats.gif")
|
|
normalized_src.setProcessor(normalized_src_processor)
|
|
# print(imp1)
|
|
normalized_white = ImagePlus() # IJ.openImage("http://imagej.nih.gov/ij/images/bridge.gif")
|
|
normalized_white.setProcessor(normalized_white_processor)
|
|
# print(imp2)
|
|
ic = ImageCalculator()
|
|
difference_image = ic.run("sub create float", normalized_src, normalized_white)
|
|
# self.debugger.on_image(imp3, 'diff')
|
|
|
|
# self.debugger.on_image(normalized_white, 'normalized_white')
|
|
# self.debugger.on_image(difference_image, 'difference_image')
|
|
|
|
# imp2mat = ImagePlusMatConverter()
|
|
# white_mat = imp2mat.toMat(white_image.getProcessor())
|
|
# white_mat = imread(white_image_file_path)
|
|
# print(white_image)
|
|
sqdiff_image = ic.run("mul create float", difference_image, difference_image)
|
|
mean_sqdiff = self.get_image_mean_value(sqdiff_image)
|
|
print('difference : ', mean_sqdiff)
|
|
if best_diff is None or mean_sqdiff < best_diff:
|
|
best_diff = mean_sqdiff
|
|
best_z_index = z_index
|
|
return best_z_index
|
|
|
|
def compute_sequence_median_image(self, sequence, channel_id='DM300_nofilter_vis'):
|
|
''' computes for each pixel its median value along time, so that in the end we have a single image that only shows structures (things that don't move such as the traps)
|
|
|
|
:param Sequence sequence:
|
|
:param str channel_id:
|
|
'''
|
|
stack = sequence.as_stack(channel_id)
|
|
projector = ZProjector()
|
|
median_image = projector.run(stack, 'median')
|
|
# pixel_value_along_time = ByteProcessor.createProcessor(stack.getDepth(), 1)
|
|
return median_image
|
|
|
|
def extract_background(self, sequence):
|
|
channel_id = 'DM300_nofilter_vis'
|
|
sequence.as_stack(channel_id).show()
|
|
background_image = self.compute_sequence_median_image(sequence, channel_id)
|
|
background_image.show()
|
|
return background_image
|
|
|
|
def estimate_white(self, sequence, channel_id):
|
|
return preprocessing.estimate_white([sequence], [channel_id], dark=None)
|
|
|
|
def process_sequence(self, sequence_id):
|
|
'''
|
|
:param str sequence_id:
|
|
'''
|
|
raise NotImplementedError()
|
|
|
|
|
|
def test_find_white():
|
|
|
|
raw_images_root = '/Users/graffy/ownCloud/ipr/lipase/raw-images'
|
|
catalog = ImageCatalog(raw_images_root)
|
|
print(catalog)
|
|
# catalog.sequences['GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0'].open_in_imagej()
|
|
# catalog.sequences['res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos2'].open_in_imagej()
|
|
# catalog.sequences['DARK_40X_60min_1 im pae min_1/Pos0'].open_in_imagej()
|
|
# catalog.sequences['white_24112018_1/Pos0'].open_in_imagej()
|
|
|
|
lipase = Lipase(catalog, debugger=ImageLogger())
|
|
sequence = lipase.catalog.sequences['res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos2']
|
|
white_seq = sequence.get_white()
|
|
channel_index = sequence.get_channel_index('DM300_327-353_fluo')
|
|
src_image_file_path = sequence.get_image_file_path(channel_index=channel_index, frame_index=0, z_index=0)
|
|
src_image = IJ.openImage(src_image_file_path)
|
|
# src_image = IJ.openImage(src_image_file_path)
|
|
depth_index = lipase.find_depth_index(src_image, white_seq)
|
|
|
|
|
|
|
|
def run_script():
|
|
test_find_white()
|
|
|
|
if False:
|
|
lipase = Lipase(ImageCatalog('/Users/graffy/ownCloud/ipr/lipase/raw-images'), debugger=ImageLogger())
|
|
lipase.process_sequence('res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos2')
|
|
|
|
if False:
|
|
sequence = lipase.catalog.sequences['GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0']
|
|
src_image_file_path = sequence.get_image_file_path(channel_index=sequence.get_channel_index('DM300_327-353_fluo'), frame_index=3)
|
|
src_image = IJ.openImage(src_image_file_path) # pylint: disable=unused-variable
|
|
|
|
# dark_image = IJ.openImage(raw_images_root + '/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0/img_000000000_DM300_327-353_fluo_000.tif')
|
|
# src_image.show()
|
|
# assert src_image
|
|
|
|
|
|
# If a Jython script is run, the variable __name__ contains the string '__main__'.
|
|
# If a script is loaded as module, __name__ has a different value.
|
|
if __name__ in ['__builtin__', '__main__']:
|
|
run_script()
|
|
# test_get_image_median_value()
|