Changeset 6848


Ignore:
Timestamp:
08/26/10 12:36:25 (9 years ago)
Author:
curtis
Message:

Various improvements to Bio-Formats MATLAB bfopen script:

  • Better handling of unsigned data types
  • Better case logic for Bio-Formats trunk vs. 4.2 stable
  • Better case logic for MATLAB 7.1+ vs. older versions
  • Better code organization, including user configuration at the top
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/components/bio-formats/utils/bfopen.m

    r6752 r6848  
    77arrays of (matrix, label) pairs, with each matrix representing a single 
    88image plane, and each inner list of matrices representing an image 
    9 series. See the bottom of this file below for examples of usage. 
     9series. See below for examples of usage. 
    1010 
    1111Portions of this code were adapted from: 
    1212http://www.mathworks.com/support/solutions/data/1-2WPAYR.html?solution=1-2WPAYR 
    1313 
    14 This method is ~1.5x-2.5x slower than Bio-Formats's command line showinf 
    15 tool (MATLAB R14 vs. java 1.6.0_20), due to overhead from copying arrays. 
     14This method is ~1.5x-2.5x slower than Bio-Formats's command line 
     15showinf tool (MATLAB 7.0.4.365 R14 SP2 vs. java 1.6.0_20), 
     16due to overhead from copying arrays. 
    1617 
    1718Thanks to all who offered suggestions and improvements: 
     
    2324    * Arnon Lieber 
    2425 
    25 Internet Explorer sometimes erroneously renames the Bio-Formats library 
    26 to loci_tools.zip. If this happens, rename it back to loci_tools.jar. 
     26NB: Internet Explorer sometimes erroneously renames the Bio-Formats library 
     27    to loci_tools.zip. If this happens, rename it back to loci_tools.jar. 
     28 
     29Here are some examples of accessing data using the bfopen function: 
     30 
     31    % read the data using Bio-Formats 
     32    data = bfopen('C:/data/experiment.lif'); 
     33 
     34    % unwrap some specific image planes from the result 
     35    numSeries = size(data, 1); 
     36    series1 = data{1, 1}; 
     37    series2 = data{2, 1}; 
     38    series3 = data{3, 1}; 
     39    metadataList = data{1, 2}; 
     40    % ...etc. 
     41    series1_numPlanes = size(series1, 1); 
     42    series1_plane1 = series1{1, 1}; 
     43    series1_label1 = series1{1, 2}; 
     44    series1_plane2 = series1{2, 1}; 
     45    series1_label2 = series1{2, 2}; 
     46    series1_plane3 = series1{3, 1}; 
     47    series1_label3 = series1{3, 2}; 
     48    % ...etc. 
     49 
     50    % plot the 1st series's 1st image plane in a new figure 
     51    series1_colorMaps = data{1, 3}; 
     52    figure('Name', series1_label1); 
     53    if isempty(series1_colorMaps{1}) 
     54        colormap(gray); 
     55    else 
     56        colormap(series1_colorMaps{1}); 
     57    end 
     58    imagesc(series1_plane1); 
     59 
     60    % Or if you have the image processing toolbox, you could use: 
     61    % imshow(series1_plane1, []); 
     62 
     63    % Or animate as a movie (assumes 8-bit unsigned data) 
     64    v = linspace(0, 1, 256)'; 
     65    cmap = [v v v]; 
     66    for p = 1:series1_numPlanes 
     67        M(p) = im2frame(uint8(series1{p, 1}), cmap); 
     68    end 
     69    movie(M); 
     70 
     71    % Query some metadata fields (keys are format-dependent) 
     72    subject = metadataList.get('Subject'); 
     73    title = metadataList.get('Title'); 
    2774%} 
    2875 
     76% -- Configuration - customize this section to your liking -- 
     77 
     78% Toggle the autoloadBioFormats flag to control automatic loading 
     79% of the Bio-Formats library using the javaaddpath command. 
     80% 
     81% For static loading, you can add the library to MATLAB's class path: 
     82%     1. Type "edit classpath.txt" at the MATLAB prompt. 
     83%     2. Go to the end of the file, and add the path to your JAR file 
     84%        (e.g., C:/Program Files/MATLAB/work/loci_tools.jar). 
     85%     3. Save the file and restart MATLAB. 
     86% 
     87% There are advantages to using the static approach over javaaddpath: 
     88%     1. If you use bfopen within a loop, it saves on overhead 
     89%        to avoid calling the javaaddpath command repeatedly. 
     90%     2. Calling 'javaaddpath' may erase certain global parameters. 
     91autoloadBioFormats = 1; 
     92 
     93% Toggle the stitchFiles flag to control grouping of similarly 
     94% named files into a single dataset based on file numbering. 
     95stitchFiles = 0; 
     96 
     97% To work with compressed Evotec Flex, fill in your LuraWave license code. 
     98%lurawaveLicense = 'xxxxxx-xxxxxxx'; 
     99 
     100% -- Main function - no need to edit anything past this point -- 
     101 
    29102% load the Bio-Formats library into the MATLAB environment 
    30 javaaddpath(fullfile(fileparts(mfilename('fullpath')),'loci_tools.jar')); 
    31 %{ 
    32 Alternately, you can add the library to MATLAB's static class path: 
    33     1. Type "edit classpath.txt" at the MATLAB prompt. 
    34     2. Go to the end of the file, and add the path to your JAR file 
    35        (e.g., C:/Program Files/MATLAB/work/loci_tools.jar). 
    36     3. Save the file and restart MATLAB. 
    37  
    38 There are advantages to using the static approach over javaaddpath: 
    39     1. If you use bfopen within a loop, it saves on overhead 
    40        to avoid calling the javaaddpath command repeatedly. 
    41     2. Calling 'javaaddpath' may erase certain global parameters. 
    42 %} 
    43  
    44 % to work with Evotec Flex, fill in your LuraWave license code 
    45 %javaaddpath(fullfile(fileparts(mfilename('fullpath')),'lwf_jsdk2.6.jar')); 
    46 %java.lang.System.setProperty('lurawave.license', 'xxxxxx-xxxxxxx'); 
     103if autoloadBioFormats 
     104    path = fullfile(fileparts(mfilename('fullpath')), 'loci_tools.jar'); 
     105    javaaddpath(path); 
     106end 
     107 
     108% set LuraWave license code, if available 
     109if exist('lurawaveLicense') 
     110    path = fullfile(fileparts(mfilename('fullpath')), 'lwf_jsdk2.6.jar'); 
     111    javaaddpath(path); 
     112    java.lang.System.setProperty('lurawave.license', lurawaveLicense); 
     113end 
     114 
     115% check MATLAB version, since typecast function requires MATLAB 7.1+ 
     116canTypecast = versionCheck(version, 7, 1); 
     117 
     118% check Bio-Formats version, since makeDataArray2D function requires trunk 
     119bioFormatsVersion = char(loci.formats.FormatTools.VERSION); 
     120isBioFormatsTrunk = versionCheck(bioFormatsVersion, 5, 0); 
    47121 
    48122r = loci.formats.ChannelFiller(); 
    49123r = loci.formats.ChannelSeparator(r); 
    50  
    51 % uncomment the following line to enable grouping of similarly 
    52 % named files into a single dataset based on file numbering 
    53 %r = loci.formats.FileStitcher(r); 
     124if stitchFiles 
     125    r = loci.formats.FileStitcher(r); 
     126end 
    54127 
    55128tic 
     
    65138    bpp = loci.formats.FormatTools.getBytesPerPixel(pixelType); 
    66139    fp = loci.formats.FormatTools.isFloatingPoint(pixelType); 
     140    sgn = loci.formats.FormatTools.isSigned(pixelType); 
     141    bppMax = power(2, bpp * 8); 
    67142    little = r.isLittleEndian(); 
    68143    numImages = r.getImageCount(); 
     
    70145    colorMaps = cell(numImages); 
    71146    for i = 1:numImages 
     147        if mod(i, 72) == 1 
     148            fprintf('\n    '); 
     149        end 
    72150        fprintf('.'); 
    73151        plane = r.openBytes(i - 1); 
     
    79157            colorMaps{s, i} = r.get16BitLookupTable()'; 
    80158        end 
    81         rowCount = size(colorMaps{s, i}, 1); 
    82         colCount = size(colorMaps{s, i}, 2); 
    83         newMap = zeros(rowCount, colCount); 
    84         for (row = 1:rowCount) 
    85             for (col = 1:colCount) 
    86                 newMap(row, col) = colorMaps{s, i}(row, col); 
    87                 pow = power(2, bpp * 8); 
    88                 if newMap(row, col) < 0 
    89                     newMap(row, col) = newMap(row, col) + pow; 
     159        if ~isempty(colorMaps{s, i}) 
     160            newMap = colorMaps{s, i}; 
     161            m = newMap(row, col) < 0; 
     162            newMap(m) = newMap(m) + bppMax; 
     163            colorMaps{s, i} = newMap / (bppMax - 1); 
     164        end 
     165 
     166        % convert byte array to MATLAB image 
     167        if isBioFormatsTrunk && (sgn || ~canTypecast) 
     168            % can get the data directly to a matrix 
     169            arr = loci.common.DataTools.makeDataArray2D(plane, ... 
     170                bpp, fp, little, height); 
     171        else 
     172            % get the data as a vector, either because makeDataArray2D 
     173            % is not available, or we need a vector for typecast 
     174            arr = loci.common.DataTools.makeDataArray(plane, ... 
     175                bpp, fp, little); 
     176        end 
     177 
     178        % Java does not have explicitly unsigned data types; 
     179        % hence, we must inform MATLAB when the data is unsigned 
     180        if ~sgn 
     181            if canTypecast 
     182                % TYPECAST requires at least MATLAB 7.1 
     183                % NB: arr will always be a vector here 
     184                switch class(arr) 
     185                    case 'int8' 
     186                        arr = typecast(arr, 'uint8'); 
     187                    case 'int16' 
     188                        arr = typecast(arr, 'uint16'); 
     189                    case 'int32' 
     190                        arr = typecast(arr, 'uint32'); 
     191                    case 'int64' 
     192                        arr = typecast(arr, 'uint64'); 
    90193                end 
    91                 newMap(row, col) = newMap(row, col) / (pow - 1); 
    92             end 
    93         end 
    94         colorMaps{s, i} = newMap; 
    95  
    96         % convert byte array to MATLAB image 
    97         arr = loci.common.DataTools.makeDataArray2D(plane, ... 
    98             bpp, fp, little, height); 
    99         % if using Bio-Formats 4.2 stable rather than trunk, 
    100         % use the following commands instead of the above line 
    101         %pix = loci.common.DataTools.makeDataArray(plane, bpp, fp, little); 
    102         %shape = [width height]; 
    103         %arr = reshape(pix, shape)'; 
     194            else 
     195                % adjust apparent negative values to actual positive ones 
     196                % NB: arr might be either a vector or a matrix here 
     197                mask = arr < 0; 
     198                adjusted = arr(mask) + bppMax / 2; 
     199                switch class(arr) 
     200                    case 'int8' 
     201                        arr = uint8(arr); 
     202                        adjusted = uint8(adjusted); 
     203                    case 'int16' 
     204                        arr = uint16(arr); 
     205                        adjusted = uint16(adjusted); 
     206                    case 'int32' 
     207                        arr = uint32(arr); 
     208                        adjusted = uint32(adjusted); 
     209                    case 'int64' 
     210                        arr = uint64(arr); 
     211                        adjusted = uint64(adjusted); 
     212                end 
     213                adjusted = adjusted + bppMax / 2; 
     214                arr(mask) = adjusted; 
     215            end 
     216        end 
     217 
     218        if isvector(arr) 
     219            % convert results from vector to matrix 
     220            shape = [width height]; 
     221            arr = reshape(arr, shape)'; 
     222        end 
    104223 
    105224        % build an informative title for our figure 
     
    156275toc 
    157276 
    158 %{ 
    159 Here are some examples of accessing data using the bfopen function: 
    160  
    161 % read the data using Bio-Formats 
    162 data = bfopen('C:/data/experiment.lif'); 
    163  
    164 % unwrap some specific image planes from the result 
    165 numSeries = size(data, 1); 
    166 series1 = data{1, 1}; 
    167 series2 = data{2, 1}; 
    168 series3 = data{3, 1}; 
    169 metadataList = data{1, 2}; 
    170 % ...etc. 
    171 series1_numPlanes = size(series1, 1); 
    172 series1_plane1 = series1{1, 1}; 
    173 series1_label1 = series1{1, 2}; 
    174 series1_plane2 = series1{2, 1}; 
    175 series1_label2 = series1{2, 2}; 
    176 series1_plane3 = series1{3, 1}; 
    177 series1_label3 = series1{3, 2}; 
    178 % ...etc. 
    179  
    180 % plot the 1st series's 1st image plane in a new figure 
    181 series1_colorMaps = data{1, 3}; 
    182 figure('Name', series1_label1); 
    183 if isempty(series1_colorMaps{1}) 
    184     colormap(gray); 
    185 else 
    186     colormap(series1_colorMaps{1}); 
    187 end 
    188 imagesc(series1_plane1); 
    189  
    190 % Or if you have the image processing toolbox, you could use: 
    191 % imshow(series1_plane1, []); 
    192  
    193 % Or animate as a movie (assumes 8-bit unsigned data) 
    194 v = linspace(0, 1, 256)'; 
    195 cmap = [v v v]; 
    196 for p = 1:series1_numPlanes 
    197     M(p) = im2frame(uint8(series1{p, 1}), cmap); 
    198 end 
    199 movie(M); 
    200  
    201 % Query some metadata fields (keys are format-dependent) 
    202 subject = metadataList.get('Subject'); 
    203 title = metadataList.get('Title'); 
    204 %} 
     277% -- Helper functions -- 
     278 
     279function [result] = versionCheck(v, maj, min) 
     280 
     281tokens = regexp(v, '[^\d]*(\d+)[^\d]+(\d+).*', 'tokens'); 
     282majToken = tokens{1}(1); 
     283minToken = tokens{1}(2); 
     284major = str2num(majToken{1}); 
     285minor = str2num(minToken{1}); 
     286result = major > maj || (major == maj && minor >= min); 
Note: See TracChangeset for help on using the changeset viewer.