diff --git a/scenePyramid.py b/scenePyramid.py index e21f9adbdd21badfa1441e41ec7cdfa66739810a..3828c118848a78348dac9ea22fece7761487a69f 100644 --- a/scenePyramid.py +++ b/scenePyramid.py @@ -155,17 +155,18 @@ class ScenePyramid: if slice_changed: self.resetScene() - # map viewport to scene - view_origin = self.view.mapToScene(0, 0) - view_max_x_y = self.view.mapToScene(self.view.width(), self.view.height()) - # get scene origin (given in microscope coords) in pixel coords scene_origin_x, scene_origin_y = (0, 0) # self.dataset.mapToPixel(p, self.microscopeMode, force=True) + # map viewport to scene + view_origin = self.view.mapToScene(scene_origin_x, scene_origin_y) + view_max_x_y = self.view.mapToScene(self.view.width(), self.view.height()) + # default width, height of view tiles view_tile_height, view_tile_width = self.tileDim inv_scaling = (1 / self.scalingFactor) ** self.currentSlice + assert inv_scaling >= 1 if self.currentSlice in self.tileWorkingSets: for i in self.tileWorkingSets[self.currentSlice]: @@ -178,9 +179,15 @@ class ScenePyramid: tile_origin_x = max(0, i * view_tile_width) + scene_origin_x tile_origin_y = max(0, j * view_tile_height) + scene_origin_y - # view tile is of constant size, but will be scaled according to slice number (scaling) - # so its appearent size in the scene will be bigger - # and it will appear at a different position + ''' + on higher slice numbers we use fewer lower res tiles to save memory + as all tiles on all slices are equal of size, for keeping the same apparent size of the scene, + we need to scale up the used tiles and shift there origin/position + view tiles are of constant size, but with higher scale (showing lower resolution) they will need + to be scaled up according to slice number + tiles will be rendered scale times bigger so its (apparent) size in the scene will be bigger + and we have to alter position + ''' t_o_x = max(0, i * inv_scaling * view_tile_width) + scene_origin_x t_o_y = max(0, j * inv_scaling * view_tile_height) + scene_origin_y @@ -402,6 +409,7 @@ class ScenePyramid: # scale lower resolution tiles up (on slice > 0) inv_scale_factor = (1 / self.scalingFactor) ** self.currentSlice + assert inv_scale_factor >= 1 item.setScale(inv_scale_factor) # and adjust position of tile accordingly @@ -409,6 +417,7 @@ class ScenePyramid: y += j * (inv_scale_factor - 1) * int(self.tileDim[self.npHeightIdx]) item.setPos(x, y) + item.setZValue(-1) item.setAcceptedMouseButtons(QtCore.Qt.NoButton) height, width, channel = img.shape @@ -460,6 +469,7 @@ class ScenePyramid: if i in pyramid_params: setattr(self, i, pyramid_params[i]) + self.fixTileDimensions() self.tileWorkingSets = copy.deepcopy(self.tileSets) self.fixMissingTiles() @@ -717,7 +727,7 @@ class ScenePyramid: warnings.simplefilter('always', Image.DecompressionBombError) warnings.simplefilter('always', Image.DecompressionBombWarning) - p['preScanModeComplete'] = True + p['scanModeComplete'] = True p['fullImageWidth'] = img.width p['fullImageHeight'] = img.height @@ -929,6 +939,27 @@ class ScenePyramid: scaling *= self.scalingFactor + + def fixTileDimensions(self): + for s in self.tileSets: + for i in self.tileSets[s]: + for j in self.tileSets[s][i]: + # as full image size might not be divisible by tile dimensions, we have to determine correct tile size + # tile numbering is 0 based + scaling = self.scalingFactor ** s + max_y, max_x = self.tileDim + fiw = scaling * self.fullImageWidth + fih = scaling * self.fullImageHeight + + tile_w = int(math.ceil(max(min(max_x, fiw - i * max_x), 0))) + tile_h = int(math.ceil(max(min(max_y, fih - j * max_y), 0))) + + is_dim = self.tileSets[s][i][j]['dimensions'] + should_dim = (tile_w, tile_h) + if is_dim != should_dim: + self.tileSets[s][i][j]['dimensions'] = should_dim + + def destruct(self): """ removes all graphics items from scene