2019-07-17 16:56:05 +02:00
""" preprocessing of synchrotron images based on telemosToolbox. """
from ij import IJ
from ij . plugin import ImageCalculator
from catalog import ImageCatalog , Sequence
2019-09-13 15:15:01 +02:00
def imagej_run_image_command ( image , command , options ) :
""" performs the given imagej command on the given image
: param ImagePlus image :
: param str command : imagej command ( eg " Gray Morphology " )
: param str options : imagej options ( eg " radius=1 type=square operator=open " )
wrapper around IJ . run ( https : / / imagej . nih . gov / ij / developer / api / ij / IJ . html #run-ij.ImagePlus-java.lang.String-java.lang.String-) which raises an exception on error
"""
IJ . run ( image , command , options )
error_message = IJ . getErrorMessage ( )
if error_message is not None :
raise Exception ( ' The command " %s " with options " %s " failed because of the following error : %s ' % ( command , options , error_message ) )
2019-07-17 16:56:05 +02:00
def compute_max ( images_file_path ) :
""" Computes for each pixel position the maximum at this position in all input images.
: param list ( str ) images_file_path :
: rtype ImagePlus :
"""
assert len ( images_file_path ) > 1
max_image = IJ . openImage ( images_file_path [ 0 ] )
print ( ' max_image ' , max_image )
for image_file_path in images_file_path [ 2 : - 1 ] :
other_image = IJ . openImage ( image_file_path )
print ( ' other_image ' , other_image )
ic = ImageCalculator ( )
ic . run ( " max " , max_image , other_image )
print ( ' max_image ' , max_image )
return max_image
def replace_outer_frame ( image , band_width ) :
""" Overwrites the outer band of the image by duplicating the value of the pixels that touch this outer band
: param ImagePlus image :
: param int band_width : width of the outer band , in pixels
: rtype ImagePlus :
adaptation for the following code from matlab telemosToolbx ' s estimatedwhiteFluoImageTelemos function
outer = white_estimate ;
white_estimate = white_estimate ( 4 : ( end - 3 ) , 4 : ( end - 3 ) ) ;
outer ( 1 : 3 , 4 : ( end - 3 ) ) = repmat ( white_estimate ( 1 , : ) , 3 , 1 ) ; # top
outer ( ( end - 2 ) : end , 4 : ( end - 3 ) ) = repmat ( white_estimate ( end , : ) , 3 , 1 ) ; # bottom
outer ( : , 1 : 3 ) = repmat ( outer ( : , 4 ) , 1 , 3 ) ; # left
outer ( : , ( end - 2 ) : end ) = repmat ( outer ( : , end - 3 ) , 1 , 3 ) ; # right
white_estimate = outer ;
clear outer ;
"""
raise NotImplementedError ( )
return image
2019-09-13 15:15:01 +02:00
def perform_gray_morphology ( image , operator , structuring_element_shape , structuring_element_radius ) :
2019-07-17 16:56:05 +02:00
"""
2019-09-13 15:15:01 +02:00
: param ImagePlus image :
: param str operator : eg ' open '
: param str structuring_element_shape : eg ' square '
: param int structuring_element_radius :
"""
assert operator not in [ ' fast open ' , ' fast erode ' ] , " as of 13/09/2019, fast operators such as ' fast erode ' seem broken in fiji (the resulting image is not at all similar to their slow equivalent) "
2019-07-17 16:56:05 +02:00
2019-09-13 15:15:01 +02:00
processor = image . getProcessor ( )
convert_to_byte = False
if processor . getBitDepth ( ) != 8 :
convert_to_byte = True
min_value = processor . getMin ( )
max_value = processor . getMax ( )
print ( " warning: downgrading image to byte as imagej ' s Gray Morphology processing doesn ' t handle 16bit images (range=[ %d , %d ]) " % ( min_value , max_value ) )
do_scaling = True
image . setProcessor ( processor . convertToByte ( do_scaling ) )
print ( " before gray morphology " )
assert structuring_element_radius < 11 , " the radius of the structuring element is too big ( %d ); using it with Fiji ' s ' Gray Morphology ' tool would result in very long computations. " % structuring_element_radius
imagej_run_image_command ( image , " Gray Morphology " , " radius= %d type= %s operator= %s " % ( structuring_element_radius , structuring_element_shape , operator ) )
print ( " after gray morphology " )
class WhiteEstimator ( object ) :
def __init__ ( self , open_size , close_size , average_size ) :
self . open_size = open_size
self . close_size = close_size
self . average_size = average_size
def _remove_particles ( self , white_estimate ) :
perform_gray_morphology ( white_estimate , operator = ' open ' , structuring_element_shape = ' square ' , structuring_element_radius = ( self . open_size + 1 ) / 2 )
perform_gray_morphology ( white_estimate , operator = ' close ' , structuring_element_shape = ' square ' , structuring_element_radius = ( self . close_size + 1 ) / 2 )
def estimate_white ( self , sequences , channel_ids , dark = None ) :
""" Estimation of the white fluorescence image shape of synchrotron light from experimental images of Telemos microscope.
: param list ( Sequence ) sequences : the sequences to consider
: param list ( str ) channel_ids : the channels to consider , eg [ ' DM300_327-353_fluo ' ]
: param WhiteEstimatorSettings white_estimator_settings :
: param ImagePlus or None dark :
: rtype ImagePlus :
Code adapted from matlab telemosToolbx ' s estimatedwhiteFluoImageTelemos function
% this function is specific of Telemos images ( DISCO line SOLEIL )
% acquired using micromanager software linked to imageJ
% % input
% nothing : interactive function
% % output
% nothing : the final reference fluorescence image is saved on disk
% % principe
% NB : MICROMANAGER save images in a structured file folder architecture :
%
% root folder : name given by the user
%
% subfolders roi ( n ) _tile1 : n folders for each selected roi
% or pos ( n ) : n folders for each selected position
%
% display_and_comments . txt : file describing the channels acquired
%
% in each subfolder roi ( n ) _tile1 or Pos ( n ) :
% images files with name img_00000000 ( n ) _DM300_327 - 353_00 ( p ) . tif
% n = number of time
% p = z focal plane
% DM300_327 - 353 = name of the channel
% metadata . txt : files describing all metadata associated with the
% acquisition : x , y , z position , camera settings . . . . etc .
%
% ( Nb : depending on the date of acquisition , an extension fluo is found or
% not in the name of fluorescence image . This extension is given in
% contrast to the visible image . )
%
% IMAGES : fluorescence images are considered
%
%
% IMPORTANT :
% it is expected that in the folders at least several images cover the whole field of view
% illuminated by the synchrtron light
% IF IT IS NOT THE CASE , IT WON ' T WORK
%
% BASIC : the estimated white image is the MAX of the selected images
% when interactive mode is selected , only first time and first z are
% proposed
% for automatic computing , all images are taken into account
%
% WHAT IS DONE :
% 0 - the user chosse the channels that are considered in the estimation of the
% white fluorescence image
%
% 1 - spurious pixels ( three lines and columns around the image ) are not taken
% in filtering and replaced by line and column number 4 and end - 3
%
% 2 - Filtering
% the estimated dark image is filtered :
% opening to remove white regions brighter than the low frequency signal that should correspond to synchrotron light shape ( should be small )
% closing to remove black regions that remains ( should be small to avoid synchrotron light shape deformation )
% average filtering
% the image computed should be used to
% - to find the best white z plane from the reference white stack
% acquired for ex . using the so called " Matthieu lame " %
% - correct images for intensities
% % use
% estimatedwhiteFluoImageTelemos
% % Comments
% adapted from proposals 20161050 and 20171187
% % Author
% MF Devaux
% INRA BIA
% PVPP
% % date
% 5 octobre 2017 :
% 23 mars 2018
% 3 septembre 2018 : comments and general case
% 16 avril 2019 : name of function and default filtering values
% 29 avril 2019 : new comments and spurious pixels
% 27 mai 2019 : offset dark
% 4 juin 2019 : replace exist by isfolder or isfile
% 14 juin : close figure at the end
"""
images_file_path = [ ]
for sequence in sequences :
for channel_id in channel_ids :
channel_index = sequence . get_channel_index ( channel_id )
for frame_index in range ( sequence . num_frames ) :
for z_index in range ( sequence . num_slices ) :
images_file_path . append ( sequence . get_image_file_path ( channel_index , frame_index , z_index ) )
white_estimate = compute_max ( images_file_path )
# modify spurious pixels on the side of the images
try :
replace_outer_frame ( white_estimate , 3 )
except NotImplementedError as error :
print ( ' warning: replace_outer_frame is not implemented yet ' )
self . _remove_particles ( white_estimate )
return white_estimate
class InteractiveWhiteEstimator ( WhiteEstimator ) :
def __init__ ( self , open_size , close_size , average_size ) :
WhiteEstimator . __init__ ( self , open_size , close_size , average_size )
def _remove_particles ( self , white ) :
""" shows the image to a user so that he can visually check that the particles have been removed correctly in the given image
"""
raise NotImplementedError ( )
# part_rem_settings_are_good = False
# while part_rem_settings_are_good == False:
# # perform opening to remove white particles
# IJ.run( white_estimate, "Gray Morphology", "radius=1 type=square operator=open" )
# # run("Gray Morphology", "radius=1 type=square operator=open");
# # IJ.run( input_image_plus_copy, "Skeletonize (2D/3D)", "" )
# # perform
# if white_estimator_settings.particles_are_removed():
# part_rem_settings_are_good = true
# else
# white_estimator_settings.ask
2019-07-17 16:56:05 +02:00
def find_white_reference_image ( white_estimate , white_z_stack ) :
""" Find the white reference Image among a z stack of reference image the most correlated to the white image estimated from a serie of acquisition.
: param Image white_estimate :
: param Sequence white_z_stack :
% this function is specific of Telemos images ( DISCO line SOLEIL )
% acquired using micromanager software linked to imageJ
% % input
% nothing : interactive function
% % output
% zmax : focal plane
% % principe
% images were acquired for a given roi which position is found in
% metadata . txt file
% white and dark images were recorded for the full field of view of the DISCO
% TELEMOS camera
%
% correlation between a estimated white fluorescence image estalished from
% actual acquisitions of a given sample and all z plane acquired for the reference TELEMOS white
% image ( Matthieu slide or any fluorescent homogeneous image ) :
% The estimated white fluorescence image is generallly obtained bt using function whiteFluoImageTelemosestimation
% This is not compulsary as any homogenous sample image hat can roughly show the shape of illumination can be used to find
% the white reference image
%
%
% the z plane for which the maximum correlation is observed between estimated white and reference white images is retained .
% the white image is then offsetted ( its corresponding Dark is subtracted ) and copied in the subfolder < WhiteReference > of the sample
% rootfolder to show that it has been specifically selected for the considered experiment
% The matlab corrcoeff function is used
%
% correlation coefficients are saved in a file called
% ' corr.txt ' in the subfolder ' WhiteReference '
%
%
% expected input folder hierarchy :
%
% > sampleFolder
% > PosFolders or RoiFolders
% > WhiteEstimate
% > darkFolder
% > darkFolder . smooth
% > whiteFolder
% > darkFolderforWhite
% > darkFolderforWhite . smooth
% > whiteFolder . smooth
%
%
% expected output folder hierarchy :
%
% > sampleFolder
% > PosFolders or RoiFolders
% > WhiteEstimate
% > WhiteReference
% > white after offset
% > darkFolder
% > darkFolder . smooth
% > whiteFolder
% > darkFolderforWhite
% > darkFolderforWhite . smooth
% > whiteFolder . smooth
% % use
% [ zmax ] = findWhiteReferenceImageTelemos
% % Comments
% written for proposal 20161050
% adapted for proposal 20170043
% % Author
% MF Devaux
% INRA BIA
% PVPP
% % date
% 5 octobre 2017 :
% 15 decembre 2017 : adapted to take into account the roi known from
% metadata
% 27 fevrier 2018 : comments details
% 4 septembre 2018 : comments and check and naming of folders
% 12 mars 2019 : save white reference with the same size as white estimate
% 16 avril 2019 : include diagonals to check the relevance of white
% reference
% 20 mai 2019 : track folder
% 27 mai 2019 : offset dark
% 4 juin 2019 : replace exist by isfolder or isfile
"""
raise NotImplementedError ( )
def test_preprocessing ( ) :
""" Test preprocessing. """
catalog = ImageCatalog ( ' /Users/graffy/ownCloud/ipr/lipase/raw-images ' )
sequence = catalog . sequences [ ' res_soleil2018/GGH/GGH_2018_cin2_phiG_I_327_vis_-40_1/Pos2 ' ]
2019-09-13 15:15:01 +02:00
white_estimator = WhiteEstimator ( open_size = 75 , close_size = 75 , average_size = 75 )
white_estimate = white_estimator . estimate_white ( [ sequence ] , [ ' DM300_327-353_fluo ' ] )
2019-07-17 16:56:05 +02:00
find_white_reference_image ( white_estimate , sequence . get_white ( ) )
if __name__ == ' __main__ ' :
test_preprocessing ( )