Skip to content

Commit

Permalink
Merge pull request #210 from will-moore/export_to_omero
Browse files Browse the repository at this point in the history
Export to omero
  • Loading branch information
jburel authored Jun 13, 2017
2 parents 12103c1 + e32835b commit cb9299f
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 21 deletions.
104 changes: 90 additions & 14 deletions omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import logging
import json
import unicodedata
import numpy

from datetime import datetime
import os
Expand Down Expand Up @@ -58,8 +59,7 @@
reportlab_installed = True
except ImportError:
reportlab_installed = False
logger.error("Reportlab not installed. See"
" https://pypi.python.org/pypi/reportlab/")
logger.error("Reportlab not installed.")


ORIGINAL_DIR = "1_originals"
Expand Down Expand Up @@ -214,7 +214,8 @@ def draw_rectangle(self, shape):
g = float(rgb[1])/255
b = float(rgb[2])/255
self.canvas.setStrokeColorRGB(r, g, b)
stroke_width = shape['strokeWidth'] * self.scale
stroke_width = shape['strokeWidth'] if 'strokeWidth' in shape else 2
stroke_width = stroke_width * self.scale
self.canvas.setLineWidth(stroke_width)

rotation = self.panel['rotation'] * -1
Expand Down Expand Up @@ -482,7 +483,7 @@ def draw_line(self, shape):

def draw_rectangle(self, shape):
# clockwise list of corner points on the OUTSIDE of thick line
w = shape['strokeWidth']
w = shape['strokeWidth'] if 'strokeWidth' in shape else 2
cx = shape['x'] + (shape['width']/2)
cy = shape['y'] + (shape['height']/2)
rotation = self.panel['rotation'] * -1
Expand Down Expand Up @@ -583,13 +584,15 @@ def get_zip_name(self):
name = name.replace(",", ".")
return "%s.zip" % name

def get_figure_file_name(self):
def get_figure_file_name(self, page=None):
"""
For PDF export we will only create a single figure file, but
for TIFF export we may have several pages, so we need unique names
for each to avoid overwriting.
This method supports both, simply using different extension
(pdf/tiff) for each.
@param page: If we know a page number we want to use.
"""

# Extension is pdf or tiff
Expand All @@ -610,7 +613,7 @@ def get_figure_file_name(self):
# Remove commas: causes problems 'duplicate headers' in file download
full_name = full_name.replace(",", ".")

index = 1
index = page if page is not None else 1
if fext == "tiff" and self.page_count > 1:
full_name = "%s_page_%02d.%s" % (name, index, fext)
if self.zip_folder_name is not None:
Expand Down Expand Up @@ -691,7 +694,7 @@ def build_figure(self):
self.add_panels_to_page(panels_json, image_ids, page)

# complete page and save
self.save_page()
self.save_page(p)

col = col + 1
if col >= page_col_count:
Expand All @@ -701,14 +704,17 @@ def build_figure(self):
# Add thumbnails and links page
self.add_info_page(panels_json)

# Saves the completed figure file
# Saves the completed figure file
self.save_figure()

# PDF will get created in this group
if group_id is None:
group_id = self.conn.getEventContext().groupId
self.conn.SERVICE_OPTS.setOmeroGroup(group_id)

return self.create_file_annotation(image_ids)

def create_file_annotation(self, image_ids):
output_file = self.figure_file_name
ns = self.ns
mimetype = self.mimetype
Expand Down Expand Up @@ -1120,6 +1126,8 @@ def draw_panel(self, panel, page, idx):
y = y - page['y']

image = self.conn.getObject("Image", image_id)
if image is None:
return None, None
self.apply_rdefs(image, channels)

# create name to save image
Expand Down Expand Up @@ -1147,6 +1155,8 @@ def get_thumbnail(self, image_id):

conn = self.conn
image = conn.getObject("Image", image_id)
if image is None:
return
thumb_data = image.getThumbnail(size=(96, 96))
i = StringIO(thumb_data)
pil_img = Image.open(i)
Expand Down Expand Up @@ -1306,6 +1316,8 @@ def add_panels_to_page(self, panels_json, image_ids, page):
# For TIFF export, draw_panel() also adds shapes to the
# PIL image before pasting onto the page...
image, pil_img = self.draw_panel(panel, page, i)
if image is None:
continue
if image.canAnnotate():
image_ids.add(image_id)
# ... but for PDF we have to add shapes to the whole PDF page
Expand All @@ -1329,7 +1341,7 @@ def create_figure(self):
self.figure_canvas = canvas.Canvas(
name, pagesize=(self.page_width, self.page_height))

def save_page(self):
def save_page(self, page=None):
""" Called on completion of each page. Saves page of PDF """
self.figure_canvas.showPage()

Expand Down Expand Up @@ -1656,7 +1668,7 @@ def draw_text(self, text, x, y, fontsize, rgb, align="center"):
# Use label as mask, so transparent part is not pasted
self.tiff_figure.paste(temp_label, (x, y), mask=temp_label)

def save_page(self):
def save_page(self, page=None):
"""
Save the current PIL image page as a TIFF and start a new
PIL image for the next page
Expand Down Expand Up @@ -1695,6 +1707,68 @@ def save_figure(self):
self.figure_canvas.save()


class OmeroExport(TiffExport):

def __init__(self, conn, script_params):

super(OmeroExport, self).__init__(conn, script_params)

self.new_image = None

def save_page(self, page=None):
"""
Save the current PIL image page as a new OMERO image and start a new
PIL image for the next page
"""
self.figure_file_name = self.get_figure_file_name(page + 1)

# Try to get a Dataset
dataset = None
for panel in self.figure_json['panels']:
parent = self.conn.getObject('Image', panel['imageId']).getParent()
if parent is not None and parent.OMERO_CLASS == 'Dataset':
if parent.canLink():
dataset = parent
break

# Need to specify group for new image
group_id = self.conn.getEventContext().groupId
if dataset is not None:
group_id = dataset.getDetails().group.id.val
dataset = dataset._obj # get the omero.model.DatasetI
self.conn.SERVICE_OPTS.setOmeroGroup(group_id)

description = "Created from OMERO.figure: "
url = self.script_params.get("Figure_URI")
legend = self.figure_json.get('legend')
if url is not None:
description += url
if legend is not None:
description = "%s\n\n%s" % (description, legend)

np_array = numpy.asarray(self.tiff_figure)
red = np_array[::, ::, 0]
green = np_array[::, ::, 1]
blue = np_array[::, ::, 2]
plane_gen = iter([red, green, blue])
self.new_image = self.conn.createImageFromNumpySeq(
plane_gen,
self.figure_file_name,
sizeC=3,
description=description, dataset=dataset)
# Reset group context
self.conn.SERVICE_OPTS.setOmeroGroup(-1)
# Create a new blank tiffFigure for subsequent pages
self.create_figure()

def create_file_annotation(self, image_ids):
"""Return result of script."""

# We don't need to create file annotation, but we can return
# the new image, which will be returned from the script
return self.new_image


def export_figure(conn, script_params):

# make sure we can find all images
Expand All @@ -1710,7 +1784,8 @@ def export_figure(conn, script_params):
fig_export = TiffExport(conn, script_params)
elif export_option == 'TIFF_IMAGES':
fig_export = TiffExport(conn, script_params, export_images=True)

elif export_option == 'OMERO':
fig_export = OmeroExport(conn, script_params)
return fig_export.build_figure()


Expand All @@ -1721,7 +1796,8 @@ def run_script():
"""

export_options = [rstring('PDF'), rstring('PDF_IMAGES'),
rstring('TIFF'), rstring('TIFF_IMAGES')]
rstring('TIFF'), rstring('TIFF_IMAGES'),
rstring('OMERO')]

client = scripts.client(
'Figure_To_Pdf.py',
Expand Down Expand Up @@ -1756,10 +1832,10 @@ def run_script():
file_annotation = export_figure(conn, script_params)

# return this file_annotation to the client.
client.setOutput("Message", rstring("Pdf Figure created"))
client.setOutput("Message", rstring("Figure created"))
if file_annotation is not None:
client.setOutput(
"File_Annotation",
"New_Figure",
robject(file_annotation._obj))

finally:
Expand Down
8 changes: 8 additions & 0 deletions omero_figure/static/figure/css/figure.css
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,14 @@
transform: rotate(90deg);
}

@keyframes spin {
100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); }
}

.navbar-right .glyphicon-refresh {
animation: spin 2s linear infinite;
padding: 2px 2px 5px 2px;
}

.colorpicker span,
.label-color span:first-child,
Expand Down
11 changes: 9 additions & 2 deletions omero_figure/templates/figure/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -711,12 +711,14 @@ <h4 class="modal-title">Open</h4>

<button id="pdf_inprogress" style="display:none" class="btn btn-primary btn-sm"
title="Figure generation in progress..." onClick="return false;">
Exporting Figure...
Exporting Figure
<span class="glyphicon glyphicon-refresh"></span>
</button>

<a id="pdf_download" href="#" target="download_pdf"
<a id="pdf_download" href="#" target="_blank"
style="padding: 4px 10px; display: none;"
class="btn btn-primary btn-sm script-result" title="Download Figure">
<!-- Tooltip and glyphicon also set on script completion in figure_view.js -->
<span class="glyphicon glyphicon-download-alt" style="font-size: 14px"></span>
</a>

Expand Down Expand Up @@ -759,6 +761,11 @@ <h4 class="modal-title">Open</h4>
<span class="glyphicon glyphicon-ok" style="color:#333; visibility:hidden"></span>
TIFF with images</a>
</li>
<li><a href="#" data-export-option="to OMERO"
title="Export each page as an Image in OMERO">
<span class="glyphicon glyphicon-ok" style="color:#333; visibility:hidden"></span>
New OMERO Image</a>
</li>
</ul>
</div>
</form>
Expand Down
23 changes: 18 additions & 5 deletions src/js/views/figure_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@
opts = {"PDF": "PDF",
"PDF & images": "PDF_IMAGES",
"TIFF": "TIFF",
"TIFF & images": "TIFF_IMAGES"};
"TIFF & images": "TIFF_IMAGES",
"to OMERO": "OMERO"};
exportOption = opts[export_opt];

// Get figure as json
Expand Down Expand Up @@ -214,10 +215,22 @@
$pdf_inprogress.hide();

// Show result
if (pdf_job.results.File_Annotation) {
var fa_id = pdf_job.results.File_Annotation.id,
fa_download = WEBINDEX_URL + "annotation/" + fa_id + "/";
$pdf_download.attr('href', fa_download).show();
if (pdf_job.results.New_Figure) {
var fa_id = pdf_job.results.New_Figure.id;
if (pdf_job.results.New_Figure.type === "FileAnnotation") {
var fa_download = WEBINDEX_URL + "annotation/" + fa_id + "/";
$pdf_download
.attr({'href': fa_download, 'data-original-title': 'Download Figure'})
.show()
.children('span').prop('class', 'glyphicon glyphicon-download-alt');
} else if (pdf_job.results.New_Figure.type === "Image") {
var fa_download = pdf_job.results.New_Figure.browse_url;
$pdf_download
.attr({'href': fa_download, 'data-original-title': 'Go to Figure Image'})
.show()
.tooltip()
.children('span').prop('class', 'glyphicon glyphicon-share');
}
} else if (pdf_job.stderr) {
// Only show any errors if NO result
var stderr_url = WEBINDEX_URL + "get_original_file/" + pdf_job.stderr + "/";
Expand Down

0 comments on commit cb9299f

Please sign in to comment.