refactor : moved catalog code in a separate module

This commit is contained in:
Guillaume Raffy 2019-07-16 14:00:24 +02:00
parent 57b3f2e074
commit 76607c19fc
2 changed files with 178 additions and 169 deletions

159
catalog.py Normal file
View File

@ -0,0 +1,159 @@
import json
class Sequence(object):
def __init__(self, catalog, sequence_id, micro_manager_metadata_file_path):
self.catalog = catalog
self.sequence_id = sequence_id
self.micro_manager_metadata_file_path = micro_manager_metadata_file_path
print(micro_manager_metadata_file_path)
with open(micro_manager_metadata_file_path, "r") as mmm_file:
self.mmm = json.load(mmm_file, encoding='latin-1') # note : the micromanager metadata files are encoded in latin-1, not utf8 (see accents in comments)
@property
def num_frames(self):
summary = self.mmm['Summary']
return int(summary['Frames'])
@property
def width(self):
summary = self.mmm['Summary']
return int(summary['Width'])
@property
def height(self):
summary = self.mmm['Summary']
return int(summary['Height'])
@property
def num_channels(self):
summary = self.mmm['Summary']
return int(summary['Channels'])
@property
def num_slices(self):
summary = self.mmm['Summary']
return int(summary['Slices'])
@property
def num_bits_per_pixels(self):
summary = self.mmm['Summary']
return int(summary['BitDepth'])
def get_root_path(self):
return '/'.join(self.micro_manager_metadata_file_path.split('/')[:-1])
def get_image_file_path(self, channel_index, frame_index, z_index=0):
'''
:param int channel_index:
:param int frame_index:
:param int z_index:
'''
assert frame_index < self.num_frames
assert channel_index < self.num_channels
frame_info = self.mmm['FrameKey-%d-%d-%d' % (frame_index, channel_index, z_index)]
rel_file_path = frame_info['FileName']
return self.get_root_path() + '/' + rel_file_path
def get_channel_index(self, channel_id):
'''
:param str channel_id:
'''
summary = self.mmm['Summary']
channel_index = summary['ChNames'].index(channel_id)
return channel_index
def get_black(self):
''' returns the black sequence related to the the sequence self
:return Sequence:
'''
seqid_to_black = {
'res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0': 'res_soleil2018/DARK/DARK_40X_60min_1 im pae min_1/Pos0',
'res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos2': 'res_soleil2018/DARK/DARK_40X_60min_1 im pae min_1/Pos0',
}
white_sequence = seqid_to_black[self.sequence_id]
return self.catalog.sequences[white_sequence]
def get_white(self):
''' returns the white sequence related to the the sequence self
:return Sequence:
'''
# assert fixme : res_soleil2018/white/white_24112018_2/Pos0 is visible
seqid_to_white = {
'res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0': 'res_soleil2018/white/white_24112018_2/Pos0',
'res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos2': 'res_soleil2018/white/white_24112018_2/Pos0',
}
white_sequence = seqid_to_white[self.sequence_id]
return self.catalog.sequences[white_sequence]
def as_hyperstack(self):
hyperstack = IJ.createHyperStack(self.sequence_id, self.width, self.height, self.num_channels, self.num_slices, self.num_frames, self.num_bits_per_pixels)
for channel_index in range(self.num_channels):
for frame_index in range(self.num_frames):
slice_index = 0
src_image_file_path = self.get_image_file_path(channel_index=channel_index, frame_index=frame_index)
# print(src_image_file_path)
src_image = IJ.openImage(src_image_file_path)
# print(src_image.getProperties())
hyperstack.setPositionWithoutUpdate(channel_index + 1, slice_index + 1, frame_index + 1)
hyperstack.setProcessor(src_image.getProcessor())
return hyperstack
def as_stack(self, channel_id):
'''
:param str channel_id: eg 'DM300_327-353_fluo'
'''
channel_index = self.get_channel_index(channel_id)
hyperstack = IJ.createHyperStack(self.sequence_id, self.width, self.height, 1, self.num_slices, self.num_frames, self.num_bits_per_pixels)
for frame_index in range(self.num_frames):
slice_index = 0
src_image_file_path = self.get_image_file_path(channel_index=channel_index, frame_index=frame_index)
# print(src_image_file_path)
src_image = IJ.openImage(src_image_file_path)
# print(src_image.getProperties())
hyperstack.setPositionWithoutUpdate(channel_index + 1, slice_index + 1, frame_index + 1)
hyperstack.setProcessor(src_image.getProcessor())
return hyperstack
def open_in_imagej(self):
# ip = IJ.createHyperStack(title=self.sequence_id, width=self.width, height= self.height, channels=1, slices=1, frames=self.get_num_frames(), bitdepth=16)
hyperstack = self.as_hyperstack()
hyperstack.show()
for channel_index in range(self.num_channels):
hyperstack.setPositionWithoutUpdate(channel_index + 1, 1, 1)
IJ.run("Enhance Contrast", "saturated=0.35")
return hyperstack
class ImageCatalog(object):
def __init__(self, raw_images_root):
self.raw_images_root = raw_images_root
self.sequences = {}
# nb : we use the path as sequence id because the "Comment" field in the summary section of the metadata file is not guaranteed to be unique (eg they are the same in res_soleil2018/white/white_24112018_1/Pos0 and in res_soleil2018/white/white_24112018_2/Pos0)
sequence_ids = []
sequence_ids.append('res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0')
sequence_ids.append('res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos2')
sequence_ids.append('res_soleil2018/DARK/DARK_40X_60min_1 im pae min_1/Pos0')
sequence_ids.append('res_soleil2018/DARK/DARK_40X_zstack_vis_327-353_1/Pos0')
# sequence_ids.append('res_soleil2018/white/white_24112018_1/Pos0') # this sequence seems broken (only 5 images while there's supposed to be 201 frames)
sequence_ids.append('res_soleil2018/white/white_24112018_2/Pos0')
for sequence_id in sequence_ids:
micro_manager_metadata_file_path = raw_images_root + '/' + sequence_id + '/metadata.txt'
# micro_manager_metadata_file_path = '/tmp/toto.json'
self.sequences[sequence_id] = Sequence(self, sequence_id, micro_manager_metadata_file_path)
def __str__(self):
for sequence_id, sequence in self.sequences.iteritems():
return str(sequence_id) + ':' + str(sequence)
# self.add_micromanager_metadata(raw_images_root + '/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0/metadata.txt')
# def add_micromanager_metadata(self, micro_manager_metadata_file_path):
# self.sequences[ micro_manager_metadata_file_path ] = Sequence(self, micro_manager_metadata_file_path)

188
lipase.py
View File

@ -1,5 +1,10 @@
# note: fiji's jython doesn't support encoding keyword
# String(label="Please enter your name",description="Name field") name
# OUTPUT String greeting
import sys
print(sys.version) # prints python version
sys.path.append('/Users/graffy/ownCloud/ipr/lipase/lipase.git') # necessary if run from fiji as script otherwise jython fails to find lipase's modules such as catalog
# A Jython script with parameters.
# It is the duty of the scripting framework to harvest
@ -12,7 +17,7 @@ from ij.process import ImageStatistics
from ij.plugin import ImageCalculator
from ij.plugin import ZProjector
from ij import WindowManager
from catalog import Sequence, ImageCatalog
# greeting = "Hello, " + name + "!"
@ -40,164 +45,6 @@ from ij import WindowManager
# 90mn : on fait un stack -> phiG_I_40x_Zstack20um_1
# - cin2 : autre échantillon similaire à cin1
# - cond[5678] : condition non réalistes
import json
class Sequence(object):
def __init__(self, catalog, sequence_id, micro_manager_metadata_file_path):
self.catalog = catalog
self.sequence_id = sequence_id
self.micro_manager_metadata_file_path = micro_manager_metadata_file_path
print(micro_manager_metadata_file_path)
with open(micro_manager_metadata_file_path, "r") as mmm_file:
self.mmm = json.load(mmm_file, encoding='latin-1') # note : the micromanager metadata files are encoded in latin-1, not utf8 (see accents in comments)
@property
def num_frames(self):
summary = self.mmm['Summary']
return int(summary['Frames'])
@property
def width(self):
summary = self.mmm['Summary']
return int(summary['Width'])
@property
def height(self):
summary = self.mmm['Summary']
return int(summary['Height'])
@property
def num_channels(self):
summary = self.mmm['Summary']
return int(summary['Channels'])
@property
def num_slices(self):
summary = self.mmm['Summary']
return int(summary['Slices'])
@property
def num_bits_per_pixels(self):
summary = self.mmm['Summary']
return int(summary['BitDepth'])
def get_root_path(self):
return '/'.join(self.micro_manager_metadata_file_path.split('/')[:-1])
def get_image_file_path(self, channel_index, frame_index, z_index=0):
'''
:param int channel_index:
:param int frame_index:
:param int z_index:
'''
assert frame_index < self.num_frames
assert channel_index < self.num_channels
frame_info = self.mmm['FrameKey-%d-%d-%d' % (frame_index, channel_index, z_index)]
rel_file_path = frame_info['FileName']
return self.get_root_path() + '/' + rel_file_path
def get_channel_index(self, channel_id):
'''
:param str channel_id:
'''
summary = self.mmm['Summary']
channel_index = summary['ChNames'].index(channel_id)
return channel_index
def get_black(self):
''' returns the black sequence related to the the sequence self
:return Sequence:
'''
seqid_to_black = {
'res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0': 'res_soleil2018/DARK/DARK_40X_60min_1 im pae min_1/Pos0',
'res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos2': 'res_soleil2018/DARK/DARK_40X_60min_1 im pae min_1/Pos0',
}
white_sequence = seqid_to_black[self.sequence_id]
return self.catalog.sequences[white_sequence]
def get_white(self):
''' returns the white sequence related to the the sequence self
:return Sequence:
'''
# assert fixme : res_soleil2018/white/white_24112018_2/Pos0 is visible
seqid_to_white = {
'res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0': 'res_soleil2018/white/white_24112018_2/Pos0',
'res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos2': 'res_soleil2018/white/white_24112018_2/Pos0',
}
white_sequence = seqid_to_white[self.sequence_id]
return self.catalog.sequences[white_sequence]
def as_hyperstack(self):
hyperstack = IJ.createHyperStack(self.sequence_id, self.width, self.height, self.num_channels, self.num_slices, self.num_frames, self.num_bits_per_pixels)
for channel_index in range(self.num_channels):
for frame_index in range(self.num_frames):
slice_index = 0
src_image_file_path = self.get_image_file_path(channel_index=channel_index, frame_index=frame_index)
# print(src_image_file_path)
src_image = IJ.openImage(src_image_file_path)
# print(src_image.getProperties())
hyperstack.setPositionWithoutUpdate(channel_index + 1, slice_index + 1, frame_index + 1)
hyperstack.setProcessor(src_image.getProcessor())
return hyperstack
def as_stack(self, channel_id):
'''
:param str channel_id: eg 'DM300_327-353_fluo'
'''
channel_index = self.get_channel_index(channel_id)
hyperstack = IJ.createHyperStack(self.sequence_id, self.width, self.height, 1, self.num_slices, self.num_frames, self.num_bits_per_pixels)
for frame_index in range(self.num_frames):
slice_index = 0
src_image_file_path = self.get_image_file_path(channel_index=channel_index, frame_index=frame_index)
# print(src_image_file_path)
src_image = IJ.openImage(src_image_file_path)
# print(src_image.getProperties())
hyperstack.setPositionWithoutUpdate(channel_index + 1, slice_index + 1, frame_index + 1)
hyperstack.setProcessor(src_image.getProcessor())
return hyperstack
def open_in_imagej(self):
# ip = IJ.createHyperStack(title=self.sequence_id, width=self.width, height= self.height, channels=1, slices=1, frames=self.get_num_frames(), bitdepth=16)
hyperstack = self.as_hyperstack()
hyperstack.show()
for channel_index in range(self.num_channels):
hyperstack.setPositionWithoutUpdate(channel_index + 1, 1, 1)
IJ.run("Enhance Contrast", "saturated=0.35")
return hyperstack
class ImageCatalog(object):
def __init__(self, raw_images_root):
self.raw_images_root = raw_images_root
self.sequences = {}
# nb : we use the path as sequence id because the "Comment" field in the summary section of the metadata file is not guaranteed to be unique (eg they are the same in res_soleil2018/white/white_24112018_1/Pos0 and in res_soleil2018/white/white_24112018_2/Pos0)
sequence_ids = []
sequence_ids.append('res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0')
sequence_ids.append('res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos2')
sequence_ids.append('res_soleil2018/DARK/DARK_40X_60min_1 im pae min_1/Pos0')
sequence_ids.append('res_soleil2018/DARK/DARK_40X_zstack_vis_327-353_1/Pos0')
# sequence_ids.append('res_soleil2018/white/white_24112018_1/Pos0') # this sequence seems broken (only 5 images while there's supposed to be 201 frames)
sequence_ids.append('res_soleil2018/white/white_24112018_2/Pos0')
for sequence_id in sequence_ids:
micro_manager_metadata_file_path = raw_images_root + '/' + sequence_id + '/metadata.txt'
# micro_manager_metadata_file_path = '/tmp/toto.json'
self.sequences[sequence_id] = Sequence(self, sequence_id, micro_manager_metadata_file_path)
def __str__(self):
for sequence_id, sequence in self.sequences.iteritems():
return str(sequence_id) + ':' + str(sequence)
# self.add_micromanager_metadata(raw_images_root + '/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos0/metadata.txt')
# def add_micromanager_metadata(self, micro_manager_metadata_file_path):
# self.sequences[ micro_manager_metadata_file_path ] = Sequence(self, micro_manager_metadata_file_path)
class IImageProcessingDebugger(object):
@ -234,18 +81,12 @@ class ImageLogger(IImageProcessingDebugger):
class Lipase(object):
def __init__(self, debugger=NullDebugger()):
def __init__(self, catalog, debugger=NullDebugger()):
'''
:param IImageProcessingDebugger im_proc_debugger:
'''
self.catalog = catalog
self.debugger = debugger
raw_images_root = '/Users/graffy/ownCloud/ipr/lipase/raw-images'
self.catalog = ImageCatalog(raw_images_root)
print(self.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()
def get_image_median_value(self, src_image):
'''
@ -350,7 +191,16 @@ class Lipase(object):
def test_find_white():
lipase = Lipase(debugger=ImageLogger())
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')
@ -364,7 +214,7 @@ def run_script():
test_find_white()
if False:
lipase = Lipase(debugger=ImageLogger())
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: