in src/wsiToDcm.cpp [501:696]
void WsiToDcm::getSlideDownSamplingLevels(
std::vector<DownsamplingSlideState> *slideDownsampleState,
SlideLevelDim *startPyramidCreationDim) {
int32_t levels;
if (retile_) {
double singleframe_downsample_width =
static_cast<double>(largestSlideLevelWidth_) /
static_cast<double>(wsiRequest_->frameSizeX);
double singleframe_downsample_height =
static_cast<double>(largestSlideLevelHeight_) /
static_cast<double>(wsiRequest_->frameSizeY);
double singleframe_downsample = std::max<double>(
singleframe_downsample_width, singleframe_downsample_height);
if (wsiRequest_->downsamples.size() > 0 &&
(wsiRequest_->stopDownsamplingAtSingleFrame ||
wsiRequest_->includeSingleFrameDownsample)) {
std::vector<int>::iterator ds_it = wsiRequest_->downsamples.begin();
double largest_ds = *ds_it;
for (; ds_it != wsiRequest_->downsamples.end(); ++ds_it) {
if (*ds_it >= singleframe_downsample) {
if (wsiRequest_->includeSingleFrameDownsample &&
*ds_it > singleframe_downsample) {
ds_it = wsiRequest_->downsamples.insert(ds_it,
singleframe_downsample);
}
largest_ds = *ds_it;
if (wsiRequest_->stopDownsamplingAtSingleFrame) {
wsiRequest_->downsamples.resize(1 +
std::distance(wsiRequest_->downsamples.begin(), ds_it));
}
break;
}
largest_ds = *ds_it;
}
if (largest_ds < singleframe_downsample &&
wsiRequest_->includeSingleFrameDownsample) {
wsiRequest_->downsamples.push_back(singleframe_downsample);
}
} else if (wsiRequest_->downsamples.size() == 0 &&
wsiRequest_->retileLevels > 0) {
int64_t single_frame_level = 1 + static_cast<int32_t>(std::ceil(
log2(singleframe_downsample)));
if ((wsiRequest_->stopDownsamplingAtSingleFrame &&
wsiRequest_->includeSingleFrameDownsample) ||
(wsiRequest_->stopDownsamplingAtSingleFrame &&
wsiRequest_->retileLevels > single_frame_level) ||
(wsiRequest_->includeSingleFrameDownsample &&
wsiRequest_->retileLevels < single_frame_level)) {
wsiRequest_->retileLevels = single_frame_level;
}
}
}
if (retile_) {
if (wsiRequest_->downsamples.size() > 0) {
levels = wsiRequest_->downsamples.size();
} else {
levels = wsiRequest_->retileLevels;
}
} else {
levels = svsLevelCount_;
}
std::unique_ptr<SlideLevelDim> smallestSlideDim = nullptr;
std::vector<std::unique_ptr<LevelProcessOrder>> levelOrderVec;
SlideLevelDim *priorSlideLevelDim;
if (startPyramidCreationDim == nullptr) {
priorSlideLevelDim = nullptr;
} else {
priorSlideLevelDim = startPyramidCreationDim;
}
for (int32_t level = wsiRequest_->startOnLevel; level < levels &&
(wsiRequest_->stopOnLevel < wsiRequest_->startOnLevel ||
level <= wsiRequest_->stopOnLevel); level++) {
BOOST_LOG_TRIVIAL(debug) << "Level: " << level;
int64_t downsample = 1;
if (retile_) {
if (wsiRequest_->downsamples.size() > level &&
wsiRequest_->downsamples[level] >= 1) {
downsample = wsiRequest_->downsamples[level];
if (level > 0 && downsample == wsiRequest_->downsamples[level - 1]) {
continue;
}
} else if (wsiRequest_->downsamples.size() == 0) {
downsample = pow(2, level);
} else {
continue;
}
}
std::unique_ptr<SlideLevelDim> tempSlideLevelDim =
std::move(getSlideLevelDim(downsample, priorSlideLevelDim));
if (tempSlideLevelDim->downsampledLevelWidth == 0 ||
tempSlideLevelDim->downsampledLevelHeight == 0) {
// frame is being downsampled to nothing skip file.
BOOST_LOG_TRIVIAL(debug) << "Layer has a 0 length dimension."
" Skipping dcm generation for layer.";
break;
}
smallestSlideDim = std::move(tempSlideLevelDim);
const int64_t frameX = std::ceil(
static_cast<double>(smallestSlideDim->downsampledLevelWidth) /
static_cast<double>(smallestSlideDim->downsampledLevelFrameWidth));
const int64_t frameY = std::ceil(
static_cast<double>(smallestSlideDim->downsampledLevelHeight) /
static_cast<double>(smallestSlideDim->downsampledLevelFrameHeight));
const int64_t frameCount = frameX * frameY;
BOOST_LOG_TRIVIAL(debug) << "Dimensions Level[" <<
level << "]: " <<
smallestSlideDim->downsampledLevelWidth <<
", " <<
smallestSlideDim->downsampledLevelHeight;
priorSlideLevelDim = smallestSlideDim.get();
levelOrderVec.push_back(std::make_unique<LevelProcessOrder>(level,
downsample,
smallestSlideDim->readFromTiff));
BOOST_LOG_TRIVIAL(debug) << "Level[" <<level << "] frames:" <<
frameX << ", " << frameY;
}
if (smallestSlideDim == nullptr) {
return;
}
// Process process levels in order of area largest to smallest.
const int32_t levelCount = static_cast<int32_t>(levelOrderVec.size());
double sourceLevelDownsample = 1.0;
int64_t instanceNumberCounter = 1;
for (int32_t idx = 0; idx < levelCount; ++idx) {
DownsamplingSlideState slideState;
const double next_cross_level_downsample =
levelOrderVec[idx]->downsample() / sourceLevelDownsample;
if (wsiRequest_->preferProgressiveDownsampling &&
next_cross_level_downsample > 8.0) {
slideState.saveDicom = false;
slideState.generateCompressedRaw = true;
slideState.instanceNumber = 0;
if (idx == 0 && slideDownsampleState->size() == 0) {
// create a virtual level for level 1.
if (startPyramidCreationDim != nullptr) {
slideState.downsample = 1.0;
slideDownsampleState->push_back(slideState);
} else {
// if getting levels from openslide get largest starting level
// which acquires imaging from highest magnification.
double starting_downsample = openslide_get_level_downsample(
getOpenSlidePtr(), 0);
if (starting_downsample != sourceLevelDownsample) {
slideState.downsample = starting_downsample;
slideDownsampleState->push_back(slideState);
}
}
}
while (levelOrderVec[idx]->downsample() / sourceLevelDownsample > 8) {
sourceLevelDownsample = sourceLevelDownsample * 8.0;
slideState.downsample = sourceLevelDownsample;
slideDownsampleState->push_back(slideState);
}
}
sourceLevelDownsample = levelOrderVec[idx]->downsample();
slideState.downsample = sourceLevelDownsample;
slideState.instanceNumber = instanceNumberCounter;
instanceNumberCounter += 1;
slideState.saveDicom = true;
slideState.generateCompressedRaw = false;
if (sourceLevelDownsample == smallestSlideDim->downsample) {
// if last slice do not save raw
slideDownsampleState->push_back(slideState);
break;
}
if (levelOrderVec[idx+1]->readLevelFromTiff()) {
// memory & compute optimization
// if next slice reads from tiff do save raw
slideDownsampleState->push_back(slideState);
continue;
} else if ((startPyramidCreationDim == nullptr) &&
(slideDownsampleState->size() == 0) &&
!levelOrderVec[idx]->readLevelFromTiff() &&
(0 == getOpenslideLevelForDownsample(
levelOrderVec[idx+1]->downsample()))) {
// Memory optimization, not reading from dicom.
// if processing an image without downsampling &
// openslide is being used to read the imaging
// (!levelOrderVec[idx]->readLevelFromTiff()
// no downsamples and reading downsample at level will also read the
// highest resolution image. Do not save compressed raw versions of
// the highest resolution. Start progressive downsampling from
// downsample level 2 and on.
slideDownsampleState->push_back(slideState);
continue;
} else {
// Otherwise save compressed slice if progressive downsampling is
// enabled.
slideState.generateCompressedRaw = wsiRequest_->
preferProgressiveDownsampling;
slideDownsampleState->push_back(slideState);
continue;
}
}
}