001/** 002 * 003 */ 004package plugins.tutorial.training; 005 006import icy.gui.dialog.MessageDialog; 007import icy.image.IcyBufferedImage; 008import icy.math.ArrayMath; 009import icy.plugin.abstract_.PluginActionable; 010import icy.sequence.Sequence; 011import icy.type.collection.array.Array1DUtil; 012 013/** 014 * Basic image processing plugin example: apply a maximum intensity projection along Z axis on the 015 * active sequence 016 * 017 * @author Stephane 018 */ 019public class MaximumZProjectionPlugin extends PluginActionable 020{ 021 022 @Override 023 public void run() 024 { 025 Sequence sequence = getActiveSequence(); 026 027 // check if a sequence is opened 028 if (sequence == null) 029 { 030 MessageDialog.showDialog("Please open a sequence to use this plugin.", MessageDialog.WARNING_MESSAGE); 031 return; 032 } 033 034 // create a new empty sequence by using the original sequence name 035 Sequence result = new Sequence(sequence.getName() + " - Z projection"); 036 037 // start sequence modification 038 result.beginUpdate(); 039 try 040 { 041 // for each frame of the sequence 042 for (int t = 0; t < sequence.getSizeT(); t++) 043 { 044 // compute the Z projection for the specified frame of sequence 045 IcyBufferedImage image = getMaxZProjection(sequence, t); 046 // set the image result at frame position t in the result Sequence 047 result.setImage(t, 0, image); 048 } 049 } 050 finally 051 { 052 // we are done with sequence modification 053 result.endUpdate(); 054 } 055 056 // make the sequence visible (add it to the GUI) 057 addSequence(result); 058 } 059 060 static IcyBufferedImage getMaxZProjection(Sequence sequence, int t) 061 { 062 // create a new image with same size and data type as the original Sequence 063 IcyBufferedImage result = new IcyBufferedImage(sequence.getSizeX(), sequence.getSizeY(), sequence.getSizeC(), 064 sequence.getDataType_()); 065 066 // for each channel of the input Sequence 067 for (int c = 0; c < sequence.getSizeC(); c++) 068 { 069 // get a direct reference on the XY planar image data array 070 Object dataArray = result.getDataXY(c); 071 072 // convert the result image data to double type for calculations 073 double[] doubleArray = Array1DUtil.arrayToDoubleArray(dataArray, result.isSignedDataType()); 074 075 // for each Z slice of the input Sequence 076 for (int z = 0; z < sequence.getSizeZ(); z++) 077 // compute the maximum between the specified slice data and the result array 078 projectMax(sequence, t, z, c, doubleArray); 079 080 // convert back the double array to original image data type 081 Array1DUtil.doubleArrayToArray(doubleArray, dataArray); 082 083 // just to let the image know the data has changed (internal updates and view refresh) and also to update cache for volatile image 084 result.setDataXY(0, dataArray); 085 } 086 087 return result; 088 } 089 090 static void projectMax(Sequence sequence, int t, int z, int c, double[] result) 091 { 092 // get XY planar image data array for the specified T, Z and C position 093 Object dataArray = sequence.getDataXY(t, z, c); 094 095 // convert to double data array 096 double[] imgDoubleArray = Array1DUtil.arrayToDoubleArray(dataArray, sequence.isSignedDataType()); 097 098 // get the maximum from the 2 input arrays and save the result 099 // into the result array by using the ArrayMath.max(..) method 100 ArrayMath.max(result, imgDoubleArray, result); 101 } 102}