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

Time reference and decimal places #481

Merged
merged 35 commits into from
Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b6c99ab
DeltaT offset from T idx (1-based)
Tom-TBT Aug 22, 2022
e6bd374
JS DeltaT offset from T idx(1-based)
Tom-TBT Aug 22, 2022
42449a2
Renamed dT offset parameter
Tom-TBT Aug 22, 2022
d2726ca
Merge branch 'ome:master' into dT_offset
Tom-TBT Sep 9, 2022
0148cd4
Default to 0 when shift with no timestamps
Tom-TBT Sep 9, 2022
7a10b1d
Added precision param to time and XYZWH labels
Tom-TBT Sep 9, 2022
33a4156
Refactoring code
Tom-TBT Sep 12, 2022
146d300
Bug fix in text between dynamic label
Tom-TBT Sep 12, 2022
18e6259
Dec prec bug fix
Tom-TBT Sep 13, 2022
c174fcb
updated tip window
Tom-TBT Sep 13, 2022
76f2897
updated format spec
Tom-TBT Sep 13, 2022
a5a27ec
limit behavior js/pdf fix
Tom-TBT Sep 13, 2022
0b9719d
Added label tests
Tom-TBT Sep 13, 2022
f5c848f
dec_prec fix when 0 with a view property
Tom-TBT Sep 13, 2022
6473162
removed alias from label tips
Tom-TBT Sep 13, 2022
40b3ffa
Removed bug fix for a separate PR
Tom-TBT Sep 13, 2022
14a6167
added mixed example to tips
Tom-TBT Sep 14, 2022
0c44a12
Updated image JSON in test
Tom-TBT Sep 14, 2022
3f05340
z.unit label bug fix for 2d images
Tom-TBT Sep 14, 2022
0870664
Merge branch 'ome:master' into dT_offset
Tom-TBT Sep 14, 2022
29d0fe1
0 default on X.unit when px size not set
Tom-TBT Sep 14, 2022
62ceba4
Merge branch 'dT_offset' of https://github.com/Tom-TBT/omero-figure i…
Tom-TBT Sep 14, 2022
55891b7
test json None px_size handling
Tom-TBT Sep 14, 2022
cbee1da
improved label tip description
Tom-TBT Sep 14, 2022
c3318df
Prettifying conditional operators
Tom-TBT Sep 14, 2022
59a4ca7
Label-parameter format change to readable
Tom-TBT Oct 4, 2022
d8c2580
style fix
Tom-TBT Oct 4, 2022
377c620
X/Y with precision 0 bug fix
Tom-TBT Oct 5, 2022
98e4439
Changed tip window on label parameter
Tom-TBT Oct 5, 2022
711920b
Bug fix of default view label precision
Tom-TBT Oct 5, 2022
0c5cf6d
Updated doc
Tom-TBT Oct 5, 2022
b06c9d2
More pythony key in dict handling
Tom-TBT Oct 6, 2022
765df8c
Initializing variables explicitly
Tom-TBT Oct 13, 2022
fd5c427
Bug fix, dataset ID
Tom-TBT Oct 13, 2022
eac902e
Style and stability adjustments
Tom-TBT Nov 3, 2022
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
9 changes: 9 additions & 0 deletions docs/figure_file_format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ Optional settings for each panel::
"size": "12",
"position": "topright",
"color": "FFFFFF"
},
{
// for 'time', 'x', 'y', 'width' and 'height', decimal precision
// parameter can be passed (here 2)
// 'time' can also be passed an offset parameter (relative to a frame, here n°3)
"text": "Time (s): [time.secs; precision=2; offset=3]",
"size": "12",
"position": "topright",
"color": "FFFFFF"
}
],

Expand Down
101 changes: 67 additions & 34 deletions omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1087,34 +1087,36 @@ def get_crop_region(self, panel):

return {'x': cropx, 'y': cropy, 'width': tile_w, 'height': tile_h}

def get_time_label_text(self, delta_t, format):
def get_time_label_text(self, delta_t, format, dec_prec):
jburel marked this conversation as resolved.
Show resolved Hide resolved
""" Gets the text for 'live' time-stamp labels """
# format of "secs" by default
is_negative = delta_t < 0
delta_t = abs(delta_t)
text = "%d s" % int(round(delta_t))
npad = 2 + dec_prec + (dec_prec > 0)
if format in ["milliseconds", "ms"]:
text = "%s ms" % int(round(delta_t * 1000))
text = "%.*f ms" % (dec_prec, delta_t * 1000)
elif format in ["secs", "seconds", "s"]:
text = "%d s" % int(round(delta_t))
text = "%.*f s" % (dec_prec, delta_t)
elif format in ["mins", "minutes", "m"]:
text = "%s mins" % int(round(delta_t / 60))
text = "%.*f mins" % (dec_prec, delta_t / 60)
elif format in ["mins:secs", "m:s"]:
m = int(delta_t // 60)
s = round(delta_t % 60)
text = "%s:%02d" % (m, s)
s = delta_t % 60
text = "%s:%0*.*f" % (m, npad, dec_prec, s)
elif format in ["hrs:mins", "h:m"]:
h = int(delta_t // 3600)
m = int(round((delta_t % 3600) / 60))
text = "%s:%02d" % (h, m)
m = (delta_t % 3600) / 60
text = "%s:%0*.*f" % (h, npad, dec_prec, m)
elif format in ["hrs:mins:secs", "h:m:s"]:
h = int(delta_t // 3600)
m = (delta_t % 3600) // 60
s = round(delta_t % 60)
text = "%s:%02d:%02d" % (h, m, s)
s = delta_t % 60
text = "%s:%02d:%0*.*f" % (h, m, npad, dec_prec, s)
else: # Format unknown
return ""
if text in ["0 s", "0:00", "0 mins", "0:00:00"]:
dec_str = "" if dec_prec == 0 else "." + "0" * dec_prec
if text in ["0"+dec_str+" s", "0:00"+dec_str,
"0"+dec_str+" mins", "0:00:00"+dec_str]:
is_negative = False
return ('-' if is_negative else '') + text

Expand Down Expand Up @@ -1162,65 +1164,90 @@ def draw_labels(self, panel, page):
last_idx = 0
for item in parse_re.finditer(l['text']):
new_text.append(l['text'][last_idx:item.start()])
expr = item.group()[1:-1].split(".")
label_value = ""

if expr[0] in ["time", "t"]:
expr = item.group()[1:-1].split(";")
prop_nf = expr[0].strip().split(".")
param_dict = {}
for value in expr[1:]:
try:
kv = value.split("=")
if len(kv) > 1:
param_dict[kv[0].strip()] = int(kv[1].strip())
except ValueError:
pass

offset = param_dict.get("offset", None)
precision = param_dict.get("precision", None)

if prop_nf[0] in ["time", "t"]:
the_t = panel['theT']
timestamps = panel.get('deltaT')
# default to index
if len(expr) == 1 or expr[1] == "index":
if len(prop_nf) == 1 or prop_nf[1] == "index":
label_value = str(the_t + 1)
else:
d_t = 0
if timestamps and the_t < len(timestamps):
d_t = timestamps[the_t]
else:
d_t = 0
label_value = self.get_time_label_text(d_t, expr[1])
if offset is not None:
if 1 <= offset <= len(timestamps):
d_t -= timestamps[offset-1]

# Set the default precision value (0) if not given
precision = 0 if precision is None else precision

label_value = self.get_time_label_text(d_t,
prop_nf[1],
precision)

elif expr[0] == "image":
format = expr[1] if len(expr) > 1 else "name"
elif prop_nf[0] == "image":
format = prop_nf[1] if len(prop_nf) > 1 else "name"
if format == "name":
label_value = panel['name'].split('/')[-1]
elif format == "id":
label_value = str(panel['imageId'])
# Escaping "_" for markdown
label_value = label_value.replace("_", "\\_")

elif expr[0] == "dataset":
format = expr[1] if len(expr) > 1 else "name"
elif prop_nf[0] == "dataset":
format = prop_nf[1] if len(prop_nf) > 1 else "name"
if format == "name":
if panel['datasetName']:
label_value = panel['datasetName']
else:
label_value = "No/Many Datasets"
elif format == "id":
if panel['datasetId']:
label_value = panel['datasetName']
label_value = str(panel['datasetId'])
else:
label_value = "null"
# Escaping "_" for markdown
label_value = label_value.replace("_", "\\_")

elif expr[0] in ['x', 'y', 'z', 'width', 'height',
'w', 'h', 'rotation', 'rot']:
format = expr[1] if len(expr) > 1 else "pixel"
elif prop_nf[0] in ['x', 'y', 'z', 'width', 'height',
'w', 'h', 'rotation', 'rot']:
format = prop_nf[1] if len(prop_nf) > 1 else "pixel"
if format == "px":
format = "pixel"
prop = expr[0]
prop = prop_nf[0]
if prop == "w":
prop = "width"
elif prop == "h":
prop = "height"
elif prop == "rot":
prop = "rotation"

# Set the default precision value (2) if not given
precision = 2 if precision is None else precision

if prop == "z":
size_z = panel.get('sizeZ')
pixel_size_z = panel.get('pixel_size_z')
z_symbol = panel.get('pixel_size_z_symbol')
if pixel_size_z is None:
pixel_size_z = 0
z_symbol = "\xB5m"

if ("z_projection" in panel.keys()
and panel["z_projection"]):
Expand All @@ -1229,8 +1256,10 @@ def draw_labels(self, panel, page):
label_value = (str(z_start + 1) + "-"
+ str(z_end + 1))
elif format == "unit" and size_z:
z_start = f"{(z_start * pixel_size_z):.2f}"
z_end = f"{(z_end * pixel_size_z):.2f}"
z_start = "%.*f" % (precision,
(z_start * pixel_size_z))
z_end = "%.*f" % (precision,
(z_end * pixel_size_z))
label_value = (z_start + " " + z_symbol + " - "
+ z_end + " " + z_symbol)
else:
Expand All @@ -1239,7 +1268,8 @@ def draw_labels(self, panel, page):
label_value = str(the_z + 1)
elif (format == "unit" and size_z
and the_z < size_z):
z_pos = f"{(the_z * pixel_size_z):.2f}"
z_pos = "%.*f" % (precision,
(the_z * pixel_size_z))
label_value = (z_pos + " " + z_symbol)

elif prop == "rotation":
Expand All @@ -1252,14 +1282,17 @@ def draw_labels(self, panel, page):
label_value = str(int(value))
elif format == "unit":
if prop in ['x', 'width']:
scale = panel['pixel_size_x']
scale = panel.get('pixel_size_x')
elif prop in ['y', 'height']:
scale = panel['pixel_size_y']
rounded = f"{(value * scale):.2f}"
scale = panel.get('pixel_size_y')
if scale is None:
scale = 0
rounded = "%.*f" % (precision,
(value * scale))
label_value = ("" + rounded +
" " + panel['pixel_size_x_symbol'])

elif expr[0] in ["channels", "c"]:
elif prop_nf[0] in ["channels", "c"]:
label_value = []
for channel in panel["channels"]:
if channel["active"]:
Expand Down
17 changes: 16 additions & 1 deletion omero_figure/templates/figure/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ <h4 class="modal-title" id="addImagesLabel">Import from JSON</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Label Formatting</h4>
</div>
<div class="modal-body" style="max-height:518px">
<div class="modal-body" style="max-height:542px">
<h4>Markdown formatting</h4>
<p>
You can use "Markdown" syntax to add formatting to plain text. For example,
Expand Down Expand Up @@ -580,6 +580,21 @@ <h4>Dynamic properties</h4>
<td>*Height*: **[height.pixel]**</td>
<td><i>Height</i>: <strong>300</strong></td>
</tr>
<tr>
<th>Width with decimal precision of 3</th>
<td>Width: [width.unit; precision=3]</td>
<td>Width: 4.450 µm</td>
jburel marked this conversation as resolved.
Show resolved Hide resolved
</tr>
<tr>
<th>Time relative to the 3rd frame</th>
<td>Time: [time.milliseconds; offset=3]</td>
<td>Time: -58 ms</td>
</tr>
<tr>
<th>Time with decimal precision 2, <br/>relative to the 3rd frame</th>
<td>Time: [time.seconds; precision=2; offset=3]</td>
<td>Time: -0.06 s</td>
</tr>
<tr>
<th>Image ID</th>
<td>Image ID: [image.id]</td>
Expand Down
67 changes: 40 additions & 27 deletions src/js/models/panel_model.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,50 +277,58 @@
else text = text + " " + c.label
}
});
return text?text:" ";
return text ? text : " ";
},

getDeltaT: function() {
var theT = this.get('theT');
return this.get('deltaT')[theT] || 0;
},

get_time_label_text: function(format) {
get_time_label_text: function(format, ref_idx, dec_prec) {
var pad = function(digit) {
var d = digit + "";
return d.length === 1 ? ("0"+d) : d;
};
var theT = this.get('theT'),
deltaT = this.get('deltaT')[theT] || 0,
isNegative = (deltaT < 0),
text = "", h, m, s;

if (ref_idx){
jburel marked this conversation as resolved.
Show resolved Hide resolved
var shift = this.get('deltaT')[parseInt(ref_idx)-1];
deltaT = shift==null ? deltaT : deltaT-shift;
}
var isNegative = (deltaT < 0);
deltaT = Math.abs(deltaT);

var padlen = dec_prec>0 ? dec_prec+3 : 2;
if (format === "index") {
isNegative = false;
text = "" + (theT + 1);
} else if (['milliseconds', 'ms'].includes(format)) {
text = Math.round(deltaT*1000) + " ms";
text = (deltaT*1000).toFixed(dec_prec) + " ms";
} else if (['seconds', 'secs', 's'].includes(format)) {
text = Math.round(deltaT) + " s";
text = deltaT.toFixed(dec_prec) + " s";
} else if (['minutes', 'mins', 'm'].includes(format)) {
text = Math.round(deltaT / 60) + " mins";
text = (deltaT / 60).toFixed(dec_prec) + " mins";
} else if (["mins:secs", "m:s"].includes(format)) {
m = parseInt(deltaT / 60);
s = pad(Math.round(deltaT % 60));
s = ((deltaT % 60).toFixed(dec_prec)).padStart(padlen, "0");
text = m + ":" + s;
} else if (["hrs:mins", "h:m"].includes(format)) {
h = parseInt(deltaT / 3600);
m = pad(Math.round((deltaT % 3600) / 60));
m = (((deltaT % 3600) / 60).toFixed(dec_prec)).padStart(padlen, "0");
text = h + ":" + m;
} else if (["hrs:mins:secs", "h:m:s"].includes(format)) {
h = parseInt(deltaT / 3600);
m = pad(parseInt((deltaT % 3600) / 60));
s = pad(Math.round(deltaT % 60));
s = ((deltaT % 60).toFixed(dec_prec)).padStart(padlen, "0");
text = h + ":" + m + ":" + s;
} else { // Format unknown
return ""
}
if (["0 s", "0:00", "0 mins", "0:00:00"].indexOf(text) > -1) {
var dec_str = dec_prec>0 ? "."+"0".repeat(dec_prec) : "";
if (["0"+dec_str+" s", "0"+dec_str+" mins", "0:00"+dec_str, "0:00:00"+dec_str].indexOf(text) > -1) {
isNegative = false;
}
return (isNegative ? '-' : '') + text;
Expand All @@ -345,32 +353,37 @@
return text;
},

get_view_label_text: function(property, format) {
get_view_label_text: function(property, format, dec_prec) {
if (format === "px") format = "pixel";

if (property === "w") property = "width";
else if (property === "h") property = "height";
else if (property === "rot") property = "rotation";


x_symbol = this.get('pixel_size_x_symbol');
z_symbol = this.get('pixel_size_z_symbol');
z_symbol = z_symbol?z_symbol:x_symbol // Using x symbol when z not defined
x_size = this.get('pixel_size_x');
y_size = this.get('pixel_size_y');
z_size = this.get('pixel_size_z');
z_size = z_size?z_size:0
var x_symbol = this.get('pixel_size_x_symbol'),
z_symbol = this.get('pixel_size_z_symbol');
z_symbol = z_symbol ? z_symbol : x_symbol // Using x symbol when z not defined
var x_size = this.get('pixel_size_x'),
y_size = this.get('pixel_size_y'),
z_size = this.get('pixel_size_z');
z_size = z_size ? z_size : 0
x_size = x_size ? x_size : 0
y_size = y_size ? y_size : 0

dec_prec = parseInt(dec_prec)
dec_prec = dec_prec==null ? 2 : dec_prec; // 2 is the default precision

var text = "";
if (property === "z") {
if (this.get('z_projection')) {
start = this.get('z_start');
end = this.get('z_end');
var start = this.get('z_start'),
end = this.get('z_end');
if (format === "pixel") {
text = "" + (start+1) + " - " + (end+1);
} else if (format === "unit"){
start = (start * z_size).toFixed(2)
end = (end * z_size).toFixed(2)
start = (start * z_size).toFixed(dec_prec)
end = (end * z_size).toFixed(dec_prec)
text = ""+ start +" "+ z_symbol
+ " - " + end +" "+ z_symbol
}
Expand All @@ -380,20 +393,20 @@
if (format === "pixel") {
text = "" + (theZ + 1);
} else if (format === "unit"){
text = ""+ (theZ * z_size).toFixed(2) +" "+ z_symbol
text = ""+ (theZ * z_size).toFixed(dec_prec) +" "+ z_symbol
}
}
return text
}
viewport = this.getViewportAsRect();
value = viewport[property];

var value = this.getViewportAsRect()[property];
if (property === "rotation") {
return ""+parseInt(value)+"°";
} else if (format === "pixel") {
return ""+parseInt(value);
} else if (format === "unit") {
scale = ['x', 'width'].includes(property) ? x_size : y_size
text = ""+ (value * scale).toFixed(2) +" "+ x_symbol
var scale = ['x', 'width'].includes(property) ? x_size : y_size
text = ""+ (value * scale).toFixed(dec_prec) +" "+ x_symbol
}
return text
},
Expand Down
Loading