Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Label on rois #600

Draft
wants to merge 54 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
99b2d64
add text field on rectangle
Rdornier Sep 6, 2024
1a10a0a
Merge branch 'master' of https://github.com/Rdornier/omero-figure int…
Rdornier Sep 9, 2024
d776a58
Merge remote-tracking branch 'origin/master' into label-on-rois
Rdornier Oct 1, 2024
b30646f
Merge branch 'master' into label-on-rois
Rdornier Nov 6, 2024
090f19e
Adding simple text label to rectangles
Rdornier Nov 6, 2024
7095371
adding fontsize
Rdornier Nov 6, 2024
9762e68
adding fill color
Rdornier Nov 6, 2024
bdec709
adding text position
Rdornier Nov 6, 2024
bbd8091
fixing rotation
Rdornier Nov 6, 2024
a6895ce
fixing text offset
Rdornier Nov 6, 2024
ac1c5be
Fixing label position with stroke width and adding corner positions
Rdornier Nov 7, 2024
d0a90bb
Fix text zoom
Rdornier Nov 7, 2024
7206309
add label on ellipses
Rdornier Nov 7, 2024
1347a52
handle rectangle rotation to position text properly
Rdornier Nov 7, 2024
d2f54e1
attempt to align text and shape rotation
Rdornier Nov 7, 2024
10c11a5
Adding toolbar + fixing text-roi overlap bug
Rdornier Nov 8, 2024
a0851fd
refactor text & rect to figure interface
Rdornier Nov 8, 2024
44554fa
adding text to the createShape method
Rdornier Nov 11, 2024
4e796a7
fix color
Rdornier Nov 11, 2024
b0afc1b
adding shape to panel and refactor x/y
Rdornier Nov 11, 2024
d59a4a0
apply zoom fraction on text offset instead of final positon
Rdornier Nov 12, 2024
e2313e5
Fixing roi reloading bug
Rdornier Nov 12, 2024
79d99a3
Fixing text anchor
Rdornier Nov 12, 2024
addeb43
Fixing text display and position on panel
Rdornier Nov 12, 2024
eca7121
Adding text to inset
Rdornier Nov 14, 2024
65a89ab
Automatic increment of inset text
Rdornier Nov 14, 2024
436e22b
delete text and increment text on inset properly
Rdornier Nov 14, 2024
58d4a6d
adding corresponding label to inset
Rdornier Nov 15, 2024
c274811
update gui and fix mousetrap
Rdornier Nov 15, 2024
e2091b9
handle copy-pasting not copying the label
Rdornier Nov 25, 2024
63e17f0
Merge branch 'master' into label-on-rois
Rdornier Nov 25, 2024
963dafa
update toolbar
Rdornier Nov 25, 2024
2204527
fix text getter and setter to be compatible with fill-color
Rdornier Nov 25, 2024
e7da396
Fix number of ROI displayed in the right panel
Rdornier Nov 25, 2024
d749b7f
Fix html layout
Rdornier Nov 25, 2024
23e9723
Merge branch 'ome:master' into label-on-rois
Rdornier Nov 27, 2024
4524d9b
Merge branch 'master' into label-on-rois
Rdornier Nov 27, 2024
e274671
delete temporary text shape when loading rois from omero
Rdornier Nov 27, 2024
83880a7
Adding text to pdf
Rdornier Nov 27, 2024
6975330
Merge branch 'ome:master' into label-on-rois
Rdornier Nov 27, 2024
57dc83f
remove empty spaces
Rdornier Nov 27, 2024
15e5160
Merge branch 'label-on-rois' of https://github.com/Rdornier/omero-fig…
Rdornier Nov 27, 2024
6a396be
Merge branch 'ome:master' into label-on-rois
Rdornier Nov 29, 2024
1bb2a89
Merge branch 'label-on-rois' of https://github.com/Rdornier/omero-fig…
Rdornier Nov 29, 2024
a57f41f
Merge commit 'refs/pull/603/head' of https://github.com/ome/omero-fig…
Rdornier Nov 29, 2024
a0b083f
Fix inset text position
Rdornier Nov 29, 2024
c1ad882
fix inset text according to stroke width
Rdornier Dec 3, 2024
0bb441f
adding scaling factor to inset
Rdornier Dec 3, 2024
30ac73f
synchronizing inset labels
Rdornier Dec 4, 2024
ec6c96b
fix flake 8 errors and markdown
Rdornier Dec 4, 2024
9b9f8b3
fix flake 8 errors
Rdornier Dec 4, 2024
3bc7003
Merge branch 'ome:master' into label-on-rois
Rdornier Dec 10, 2024
fd13b0c
Merge branch 'ome:master' into label-on-rois
Rdornier Dec 16, 2024
355e252
Merge branch 'ome:master' into label-on-rois
Rdornier Jan 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
*.pyc
.DS_Store
.omero
.idea
.vscode
demo/omero_figure/
demo/figure.js
demo/index.html
Expand Down
61 changes: 52 additions & 9 deletions omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,14 @@ def draw_point(self, shape):
class ShapeToPdfExport(ShapeExport):
point_radius = 5

def __init__(self, canvas, panel, page, crop, page_height):
def __init__(self, canvas, panel, page, crop, page_height, page_width):

self.canvas = canvas
self.page = page
# The crop region on the original image coordinates...
self.crop = crop
self.page_height = page_height
self.page_width = page_width
# Get a mapping from original coordinates to the actual size of panel
self.scale = float(panel['width']) / crop['width']

Expand All @@ -304,9 +305,9 @@ def panel_to_page_coords(self, shape_x, shape_y):
h_flip = self.panel.get('horizontal_flip', False)
v_flip = self.panel.get('vertical_flip', False)
if h_flip:
shape_x = self.crop['width'] - shape_x + 2*self.crop['x']
shape_x = self.crop['width'] - shape_x + 2 * self.crop['x']
if v_flip:
shape_y = self.crop['height'] - shape_y + 2*self.crop['y']
shape_y = self.crop['height'] - shape_y + 2 * self.crop['y']

rotation = self.panel['rotation']
if v_flip != h_flip:
Expand Down Expand Up @@ -370,6 +371,48 @@ def draw_shape_label(self, shape, bounds):
para.drawOn(
self.canvas, center[0] - w / 2, center[1] - h / 2 + size / 4)

def draw_text(self, shape):
text_coords = self.panel_to_page_coords(shape['x'], shape['y'])
text = ""

if markdown_imported:
# convert markdown to html
text = markdown.markdown(shape.get('text'))

size = shape.get('fontSize', 12)
stroke_width = shape.get('strokeWidth', 2)
r, g, b, a = self.get_rgba(shape['strokeColor'])
# bump up alpha a bit to make text more readable
rgba = (r, g, b, 0.5 + a / 2.0)

x = text_coords["x"]
y = self.page_height - text_coords["y"]
anchor = shape['textAnchor']
aligment = TA_LEFT

if (anchor == 'middle'):
aligment = TA_CENTER
x = x - (self.page_width / 2)
elif (anchor == "end"):
aligment = TA_RIGHT
x = x - self.page_width

style = ParagraphStyle(
'label',
parent=getSampleStyleSheet()['Normal'],
alignment=aligment,
textColor=Color(*rgba),
fontSize=size,
leading=size,
)
para = Paragraph(text, style)

w, h = para.wrap(self.page_width, 100)
para.drawOn(
self.canvas,
x + int(stroke_width * 0.25),
y - h / 2 - int(size * 0.25) - int(stroke_width * 0.25))

def draw_line(self, shape):
start = self.panel_to_page_coords(shape['x1'], shape['y1'])
end = self.panel_to_page_coords(shape['x2'], shape['y2'])
Expand Down Expand Up @@ -599,9 +642,9 @@ def get_panel_coords(self, shape_x, shape_y):

# Apply flip transformations to the shape coordinates
if h_flip:
shape_x = self.crop['width'] - shape_x + 2*self.crop['x']
shape_x = self.crop['width'] - shape_x + 2 * self.crop['x']
if v_flip:
shape_y = self.crop['height'] - shape_y + 2*self.crop['y']
shape_y = self.crop['height'] - shape_y + 2 * self.crop['y']

rotation = self.panel['rotation']
if v_flip != h_flip:
Expand Down Expand Up @@ -733,7 +776,7 @@ def draw_rectangle(self, shape):
# with correct stroke width
r, g, b, a = self.get_rgba_int(shape.get('fillColor', '#00000000'))
if 'fillOpacity' in shape:
a = int(float(shape['fillOpacity'])*255)
a = int(float(shape['fillOpacity']) * 255)
rgba = (r, g, b, a)

# need to draw on separate image and then paste on to get transparency
Expand Down Expand Up @@ -792,7 +835,7 @@ def draw_polygon(self, shape, closed=True):
# with correct stroke width
r, g, b, a = self.get_rgba_int(shape.get('fillColor', '#00000000'))
if 'fillOpacity' in shape:
a = int(float(shape['fillOpacity'])*255)
a = int(float(shape['fillOpacity']) * 255)
rgba = (r, g, b, a)

# need to draw on separate image and then paste on to get transparency
Expand Down Expand Up @@ -878,7 +921,7 @@ def draw_ellipse(self, shape):

r, g, b, a = self.get_rgba_int(shape.get('fillColor', '#00000000'))
if 'fillOpacity' in shape:
a = int(float(shape['fillOpacity'])*255)
a = int(float(shape['fillOpacity']) * 255)
rgba = (r, g, b, a)

# when rx is ~zero (for a Point, scaled down) don't need inner ellipse
Expand Down Expand Up @@ -1281,7 +1324,7 @@ def add_rois(self, panel, page):

crop = self.get_crop_region(panel)
ShapeToPdfExport(self.figure_canvas, panel, page, crop,
self.page_height)
self.page_height, self.page_width)

def draw_labels(self, panel, page):
"""
Expand Down
4 changes: 4 additions & 0 deletions src/css/figure.css
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,10 @@
padding-left: 3px;
padding-right: 3px;
}
.text-group{
padding-left: 0px;
padding-right: 0px;
}
.navbar-nav > li > a {
padding-bottom: 12px;
padding-top: 12px;
Expand Down
15 changes: 0 additions & 15 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -209,21 +209,6 @@ <h5 class="modal-title" style="float: left; padding-right: 20px">
</div>
</div>
<div id="roiModalSidebar" class="col-4" style="padding: 0">
<span
id="roiPageControls"
style="color: #999; line-height: 30px"
>
</span>
<div style="clear: both"></div>
<div style="padding: 0; height: 550px; overflow-y: auto; position: relative;">
<div id="roiModalRoiList">
<table
style="width: 100%"
class="table table-hover table-condensed"
></table>
</div>
<p id="roiModalTip" style="position: absolute; top: 0"></p>
</div>
</div>
</div>
<div class="modal-footer" style="margin-top: 0">
Expand Down
57 changes: 54 additions & 3 deletions src/js/models/panel_model.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

initialize: function() {
// listen for changes to the viewport...
this.on("change:zoom change:dx change:dy change:width change:height change:rotation", (panel) => {
this.on("change:zoom change:dx change:dy change:width change:height change:rotation change:labels", (panel) => {
// if this panel has 'insetRoiId' it is an "inset" panel so we need to
// notify other panels that contain the corresponding ROI (rectangle)
if (this.get('insetRoiId') && this.figureModel) {
Expand Down Expand Up @@ -81,8 +81,24 @@

// find Rectangle from panel that corresponds to this panel
let rect = (panel.get("shapes") || []).find(shape => shape.id == insetRoiId);

if (rect) {
this.cropToRoi(rect);
let text = panel.get("shapes").find(shape => shape.id == rect.textId);
if(text){
let insetLabel = (this.get("labels") || []).find(lbl => lbl.inset == true);
if(insetLabel){
var lbl_key = this.get_label_key(insetLabel)
var new_txt = "**"+text.text+"**"
if(insetLabel.text !== new_txt){
insetLabel.text = new_txt
var newlbls = {};
newlbls[lbl_key] = insetLabel;
this.edit_labels(newlbls)
this.trigger("change:labels")
}
}
}
}

this.silenceTriggers = false;
Expand All @@ -92,6 +108,8 @@
// An inset panel has zoomed/panned or deleted. If we have corresponding inset
// Rectangle then update or delete it accordingly...
var insetRoiId = panel.get('insetRoiId');
var inset_lbl = panel.get('labels').filter(lbl => lbl.inset == true);

if (!insetRoiId) return;
// find Rectangles that have insetRoiId...
let insetShapes = this.get('shapes');
Expand All @@ -105,24 +123,51 @@
// Delete the inset Rectangle IF there are NO other remaining insets
let insets = figureModel.panels.filter(p => p.get('insetRoiId') == insetRoiId);
if (insets.length == 0) {
updated = updated.filter(shape => shape.id != insetRoiId);
let rect = updated.filter(shape => shape.id == insetRoiId);
updated = updated.filter(shape => (shape.id != insetRoiId && shape.id != rect[0].textId));
this.save('lastInsetTextIndex', this.get('lastInsetTextIndex') - 1)
}
this.save('shapes', updated);
} else {
let rect = panel.getViewportAsRect();
let textId = -1;
updated = updated.map(shape => {
if (shape.type == 'Rectangle' && shape.id == insetRoiId) {
textId = shape.textId
return {...shape, ...rect}
}
return shape;
});
updated = updated.map(shape => {
if (shape.type == 'Text' && shape.id == textId) {
var prev = shape.parentShapeCoords
shape.parentShapeCoords = {...rect}
shape.x = shape.x + rect.x - prev.x
shape.y = shape.y + rect.y - prev.y
if(inset_lbl && inset_lbl[0]){
if(inset_lbl[0].text !== shape.text){
shape.text = inset_lbl[0].text.replaceAll("*","")
}
}
}
return shape;
});
this.save('shapes', updated);
this.trigger("change:shapes")
}
this.silenceTriggers = false;
}
}
},

getLastInsetTextIndex: function(){
return this.get('lastInsetTextIndex')
},

setLastInsetTextIndex: function(index){
this.save('lastInsetTextIndex', index)
},

// When we're creating a Panel, we process the data a little here:
parse: function(data, options) {
var greyscale = data.rdefs.model === "greyscale";
Expand Down Expand Up @@ -303,6 +348,8 @@
points = shape.points.split(' ').map(function(p){
return p.split(",");
});
} else if (shape.type === "Text"){
points = [[shape.x, shape.y]];
}
if (points) {
for (var p=0; p<points.length; p++) {
Expand Down Expand Up @@ -602,7 +649,11 @@
if (labels_map.hasOwnProperty(lbl_key)) {
if (labels_map[lbl_key]) {
// replace with the new label
lbl = $.extend(true, {}, labels_map[lbl_key]);
var new_lbl = labels_map[lbl_key]
if(lbl.inset){
new_lbl.inset = true
}
lbl = $.extend(true, {}, new_lbl);
labs.push( lbl );
}
// else 'false' are ignored (deleted)
Expand Down
29 changes: 26 additions & 3 deletions src/js/shapeEditorTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
// disclaimer in the documentation // and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
// BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS
Expand Down Expand Up @@ -78,6 +78,21 @@ $(function() {
shapeManager.setFillOpacity(fillOpacity);
});

$("select[name='fontSize']").change(function(){
var fontSize = $(this).val();
shapeManager.setTextFontSize(fontSize);
});

$("select[name='textPosition']").change(function(){
var textPosition = $(this).val();
shapeManager.setTextPosition(textPosition);
});

$("select[name='rotateText']").change(function(){
var rotateText = $(this).val();
shapeManager.setTextRotated(rotateText);
});

var updateZoom = function updateZoom() {
$("#zoomDisplay").text(zoomPercent + " %");
shapeManager.setZoom(zoomPercent);
Expand Down Expand Up @@ -111,6 +126,14 @@ $(function() {
shapesClipboard = shapeManager.getSelectedShapesJson();
});

$("button[name='setText']").click(function(){
shapeManager.setText("A");
});

$("button[name='clearText']").click(function(){
shapeManager.setText("");
});

$("button[name='pasteShapes']").click(function(){
// paste shapes, constraining to the image coords
var p = shapeManager.pasteShapesJson(shapesClipboard, true);
Expand Down Expand Up @@ -200,7 +223,7 @@ $(function() {
"strokeWidth": 4});

shapeManager.addShapeJson({"id": 1234,
"rotation": 45,
"rotation": 25,
"type": "Rectangle",
"strokeColor": "#ff00ff",
"strokeWidth": 6,
Expand Down
Loading