diff --git a/code/INI/readStitchItINI.m b/code/INI/readStitchItINI.m index 66adeac..d1af590 100644 --- a/code/INI/readStitchItINI.m +++ b/code/INI/readStitchItINI.m @@ -22,7 +22,7 @@ % Inputs % All inputs as *optional* parameter/value pairs % 'INIfname' - Path to INI file to read. If empty or missing the above rules apply. -% 'systemType' = either 'TissueCyte' or the ID of a system (the microscope name). +% 'systemType' = The ID of a system (the microscope name). % % Outputs % out - the contents of the INI file (plus some minor processing) as a structure @@ -130,29 +130,18 @@ end -%Pull out the current objective from the structure -% TODO: the following is system specific and very much tied to the TV. -% Need to get rid of it -- too complicated -if ~isfield(out, out.experiment.objectiveName) - error('No objective name field %s found\nPlease check your INI file!', out.experiment.objectiveName') -end -thisObjective = out.(out.experiment.objectiveName); -%Note that for TV data sets, the number of microns per pixel is with respect to the 1664 image size -out.micsPerPixel.micsPerPixelMeasured=thisObjective.micsPerPixelMeasured; -out.micsPerPixel.micsPerPixelRows=thisObjective.micsPerPixelRows; -out.micsPerPixel.micsPerPixelCols=thisObjective.micsPerPixelCols; function out=readThisINI(fname) -ini = IniConfig(); -ini.ReadFile(fname); + ini = IniConfig(); + ini.ReadFile(fname); -sections = ini.GetSections; + sections = ini.GetSections; -for ii=1:length(sections) - keys = ini.GetKeys(sections{ii}); - values = ini.GetValues(sections{ii}, keys); - for jj=1:length(values) - out.(sections{ii}(2:end-1)).(keys{jj})=values{jj}; + for ii=1:length(sections) + keys = ini.GetKeys(sections{ii}); + values = ini.GetValues(sections{ii}, keys); + for jj=1:length(values) + out.(sections{ii}(2:end-1)).(keys{jj})=values{jj}; + end end -end diff --git a/code/INI/stitchitConf_DEFAULT.ini b/code/INI/stitchitConf_DEFAULT.ini index c18fdbc..07363de 100644 --- a/code/INI/stitchitConf_DEFAULT.ini +++ b/code/INI/stitchitConf_DEFAULT.ini @@ -30,78 +30,6 @@ stitchedDirBaseName=stitchedImages WEBdir=forWWW -;;---------------------------------------------------------------------------- -;; Our TissueVision system does not correctly report the number of microns per -;; pixel in the Mosaic file. We therefore measured this and the following few -;; sections are responsible for correctly telling StitchIt what this value is. -;; We define the number of microns per pixel with respect to a particular image -;; size. It might have been better to define it using scan angle, but right now -;; we do it with respect to an image size of 1664 x 1664. -;; Note that [experiment], [micsPerPixel], and the objective sections are only -;; for the TissueVision. We assume that other systems will correctly report the -;; number of microns per pixel in the image meta-data. - -;;---------------------------------------------------------------------------- -[experiment] -;; Set this to be the objective used in your experiment. This value is -;; used to determine where to place the tiles. Its name must correspond to one of the -;; the objective name sections below. The _x_x that suffixes some names refers to the -;; scan angle. e.g. _2_2 is a scan angle of 2.2 -objectiveName=Nikon16x_2_2 -;;objectiveName=Nikon16x_3_0 -;;objectiveName=Zeiss20x - - - -;;---------------------------------------------------------------------------- -;;This section determines how StitchIt will calculate the number of microns -;;per pixel. This is important because StitchIt uses this number to position -;;the tiles. It needs to know the number of microns per pixel both for -;;naive positioning and stage coordinate positioning. -;; - - -[micsPerPixel] -;;We calculate the number of microns per pixel by imaging an EM grid. The number of -;;microns per pixel must be in reference to a particular image size. This is defined -;;here. e.g. 1664 by 1664 pixels -numPix=1664 - -;;The following setting allows us to choose whether we want to use a single number -;;for both X and Y or different numbers. Using a single number (usemeasured=1) -;;causes us to use "micsPerPixel" and setting usemeasured to 0 casuses us to use -;;the two separate row and col values. The need to tweak the number may arise from -;;the sampling accuracy of the measurements which creates rounding errors in the FFT. -;;1 means use the measured, single, value for both x and y. 0 means use the other -;;two values (micsPerPixelRows and micsPerPixelCols. -usemeasured=0 - - -;; Objectives follow - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -[Zeiss20x] -;;In case the user tweaks this value, we log here in the comments that the -;;default value for the 20x at 1664^2 is 0.485 microns/pixel -micsPerPixelMeasured=0.485 - -;;The following two numbers are based on the above but tweaked. The -;;tweaking was done by trying out a bunch of different conversion factors -;;and seeing what worked best. They allow for setting different numbers -;;of microns per pixel in x and y. This may not be necessary and may be -;;removed in future. -micsPerPixelRows=0.468 -micsPerPixelCols=0.450 - - -[Nikon16x_2_2] -micsPerPixelMeasured=0.480 -micsPerPixelRows=0.474 -micsPerPixelCols=0.459 - -[Nikon16x_3_0] -micsPerPixelMeasured=0.650 -micsPerPixelRows=0.650 -micsPerPixelCols=0.650 - ;;---------------------------------------------------------------------------- diff --git a/code/preProcessTiles/preProcessTiles.m b/code/preProcessTiles/preProcessTiles.m index 4cd16d5..3e43538 100644 --- a/code/preProcessTiles/preProcessTiles.m +++ b/code/preProcessTiles/preProcessTiles.m @@ -119,9 +119,8 @@ verbose=params.Results.verbose; -if ~strcmp(determineStitchItSystemType,'TissueCyte') && ... - (length(combCorChans)>1 || combCorChans~=0) - fprintf('\nYou have requested to run a comb-correction on non-TissueVision data. Please see:\n ') +if length(combCorChans)>1 || combCorChans~=0 + fprintf('\nYou have requested to run a comb-correction. This is not working right now. Please see:\n ') fprintf('https://github.com/BaselLaserMouse/StitchIt/wiki/Tile-pre-processing\n\n') end diff --git a/code/stitching/determineStitchedImageExtent.m b/code/stitching/determineStitchedImageExtent.m index 1b359b1..b98bdff 100644 --- a/code/stitching/determineStitchedImageExtent.m +++ b/code/stitching/determineStitchedImageExtent.m @@ -7,7 +7,7 @@ % With auto-ROI the sections will be very different sizes. In order to produces a series of % stitched images having the same size from section to section we need to determine the % locations of all the tiles in the whole sample and find the extrema in the x/y plane. - % This functio does this. + % This function does this. % % Inputs - none. just run from sample directory % @@ -18,6 +18,13 @@ % Rob Campbell - SWC 2020 + verbose=true; %report to screen lots on info on + plotboxes=true; %make a plot with the imaged areas overlain + + if verbose + fprintf('%s is determining the extent of the imaged area\n', mfilename) + end + out=[]; [data,successfulRead]=readMetaData2Stitchit; @@ -42,6 +49,7 @@ out.maxXPos = nan(1,length(rDataDirs)); out.maxYPos = nan(1,length(rDataDirs)); + tp = {}; %cache all loaded position arrays in case we want to do stuff with them later for ii=1:length(rDataDirs) posFname = fullfile(userConfig.subdir.rawDataDir,rDataDirs(ii).name,'tilePositions.mat'); if ~exist(posFname,'file') @@ -49,23 +57,107 @@ end load(posFname,'positionArray') + tp{ii} = positionArray; - % Log the minimum X and Y positions + % Log the actual minimum X and Y positions + % TODO - we should maybe allow for predicted stage positions instead of actual out.minXPos(ii)=min(positionArray(:,5)); out.minYPos(ii)=min(positionArray(:,6)); out.maxXPos(ii)=max(positionArray(:,5)); out.maxYPos(ii)=max(positionArray(:,6)); + if verbose + fprintf('%d/%d Front/Left -- x=%0.2f y=%0.2f (%d by %d tiles)\n', ... + ii, ... + length(rDataDirs), ... + out.maxXPos(ii), ... + out.maxYPos(ii), ... + length(unique(positionArray(:,1))), ... + length(unique(positionArray(:,2))) ) + end end - tileStepSizeMM = abs(mode(diff(positionArray(:,3)))) - + % The tile step size is the distance moved by the microscope in mm as it travels from one x/y stage + % location to the next. It is equal to the tile size (image FOV) minus the overlap between tiles. + tileStepSizeMM = abs(mode(diff(positionArray(:,3)))); + % The tile extent in mm is the image FOV tileExtentInMM = tileStepSizeMM / (1-data.mosaic.overlapProportion); - - %out.minXY = [min(out.minXPos), min(out.minYPos)] - tileExtentInMM; % % TODO -- I would have thought this is correct, but it seems not to be + + % The number of mm of overlap between adjacent tiles + tileOverlapInMM = tileExtentInMM - tileStepSizeMM; + out.minXY = [min(out.minXPos), min(out.minYPos)] - tileStepSizeMM; - out.maxXY = [max(out.maxXPos), max(out.maxYPos)]; + + out.maxXY = [max(out.maxXPos), max(out.maxYPos)]; % This is the "origin" front/left + + + % This is a call to a test function to ensure that all is running as expected + checkMinMax + + + if plotboxes + % Use the minimum x/y position and the tile position array to produce pixel positions for + % where the tiles ought to go. + voxSize = [data.voxelSize.X, data.voxelSize.Y]; + tileStep = [(tileStepSizeMM*1E3) / voxSize(1), (tileStepSizeMM*1E3) / voxSize(2)]; + tileSizeInPixels = [(tileExtentInMM*1E3) / voxSize(1), (tileExtentInMM*1E3) / voxSize(2)]; + figure(4592) + clf + hold on + jj = jet(length(rDataDirs)); + for ii=1:length(rDataDirs) + + tmp=stagePos2PixelPos(tp{ii}(:,5:6), voxSize, out.maxXY); + minPix = min(tmp); + maxPix = max(tmp) + tileSizeInPixels; + d = maxPix-minPix; % This is the size of the box + + % Plot the box + x = [minPix(2), minPix(2), minPix(2)+d(2), minPix(2)+d(2), minPix(2)]; + y = [minPix(1), minPix(1)+d(1), minPix(1)+d(1), minPix(1), minPix(1)]; + plot(x, y, '-', 'Color', jj(ii,:), 'LineWidth', 2) + + % Print to screen the size and location of the box + fprintf('%d/%d %dx%d pixels. With far corner at pixel pos %d/%d (%0.2f by %0.2f tile step sizes).\n', ... + ii, length(rDataDirs), ... + ceil(d), ... + ceil(max(x)), ceil(max(y)), ... + d(1)/tileStep(1), d(2)/tileStep(2)) + fprintf(' min pixel: %d / %d\n\n', ceil(min(x)), ceil(min(y))) + end + hold off + axis ij + end + + + + + function checkMinMax + % This is somewhat of a test function. If the min and max positions we have extracted are all + % correct, we should fit an integer number of tiles into the space they demarcate for each section. + fprintf('Do the min/max stage coords results in an integer number of tiles?\n') + + for ii = 1:length(out.minYPos) + + % If we just do the following we will be num tiles minus 1 because it does not + % take into account the area imaged by the final tile row and tile column. + dX = out.maxXPos(ii) - out.minXPos(ii); + dY = out.maxYPos(ii) - out.minYPos(ii); + + % Therefore we add one tile step size (tile FOV minus the overlap) + dX = out.maxXPos(ii) - out.minXPos(ii) + tileStepSizeMM; + dY = out.maxYPos(ii) - out.minYPos(ii) + tileStepSizeMM; + fprintf('%d/%d. Tiles plus on step size: %0.1f x %0.1f\n', ... + ii, length(out.minYPos), ... + dX/tileStepSizeMM, dY/tileStepSizeMM) + + end + end %checkMinMax + + +end % Main enclosing function + diff --git a/code/stitching/gridPos2Pixels.m b/code/stitching/gridPos2Pixels.m index 0ced22f..eeee611 100644 --- a/code/stitching/gridPos2Pixels.m +++ b/code/stitching/gridPos2Pixels.m @@ -26,7 +26,7 @@ % stepSize - step in microns between one tile and the next. If a scalar the step size is the same in both % rows and columns. If a vector of length 2, it defines the step size along the rows (1) and % cols (2). By default stepSize is obtained from the parameter file. -% +% % % OUTPUTS % pixelPositions - n by 2 array. n tiles. [pixel row, pixel column] @@ -40,29 +40,6 @@ tileCol = tileCoords(:,2); -if nargin<2 | isempty(pixelRes) %read in number of microns per pixel if needed - - userConfig=readStitchItINI; - if userConfig.micsPerPixel.usemeasured - pixResR = userConfig.micsPerPixel.micsPerPixelMeasured; - pixResC = userConfig.micsPerPixel.micsPerPixelMeasured; - else - pixResR = userConfig.micsPerPixel.micsPerPixelRows; - pixResC = userConfig.micsPerPixel.micsPerPixelCols; - end - -else - - if length(pixelRes)==1 - pixResR = pixelRes; - pixResC = pixelRes; - elseif length(pixelRes)>1 - pixResR = pixelRes(1); - pixResC = pixelRes(2); - end - -end - if nargin<3 | isempty(stepSize) M=readMetaData2Stitchit; diff --git a/code/stitching/stitchAllChannels.m b/code/stitching/stitchAllChannels.m index 4680678..be10e40 100644 --- a/code/stitching/stitchAllChannels.m +++ b/code/stitching/stitchAllChannels.m @@ -48,12 +48,6 @@ function stitchAllChannels(chansToStitch,stitchedSize,illumChans,combCorChans) return end -%Bail out if we can't determin the acquisition system name -if determineStitchItSystemType<1 - %error message generated by determineStitchItSystemType - return -end - % Check input arguments if nargin<1