Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions components/blitz/resources/omero/Constants.ice
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ module omero {
const string NSCOMPANIONFILE = "openmicroscopy.org/omero/import/companionFile";
const string NSEXPERIMENTERPHOTO = "openmicroscopy.org/omero/experimenter/photo";
const string NSBULKANNOTATIONS = "openmicroscopy.org/omero/bulk_annotations";
const string NSOMETIFF = "openmicroscopy.org/omero/ome_tiff";
//
// omero.grid.Param.namespaces in Scripts.ice
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,32 @@ button::-moz-focus-inner {
height:18px;
display:block;
}

#general_tab .btn_download span {
width:20px;
height:18px;
display:block;
}

#general_tab .btn_download {
background: url(../../webgateway/img/icon_download2.png) center center no-repeat;
}

#download_dropdown {
float:right;
margin: 0px 5px;
}
#download_dropdown .dropdown {
right: 0px;
left: auto;
}
#download_dropdown .dropdown:before {
left: 68% !important;
}
#download_dropdown ul a {
background: none;
font-size: 80%;
}



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,63 @@
return false;
});


// -- Download options --
$("#download_dropdown ul").css('visibility', 'hidden');
// show on click
$("#show_download_dropdown").click(function(e) {
$("ul", $(this).parent()).css('visibility', 'visible');
e.preventDefault();
return false;
});
// on hover-out, hide drop-down menus
$("#download_dropdown ul").hover(function(){}, function(){
$(this).css('visibility', 'hidden');
});

// Handle Download actions
$("#create-ometiff").click(function(e){

var url = $(this).attr('href');
$("#download_dropdown ul").css('visibility', 'hidden');// hide dropdown menu
var dialog_opts = ['Cancel', 'Create'];
$.getJSON("{% url ome_tiff_info manager.obj_id %}", function(data) {

var msg = "This will create an OME-TIFF file from this Image.";
if (data.id && data.ago) {
msg += "<br>Or you can Download one that was created "+ data.ago +" ago.";
var download_ometiff = data.download;
dialog_opts[1] = "Create New";
dialog_opts.push("Download");
} else {
msg += "<br>This will be attached to the Image and available to download.";
}

var confirm_ometiff = confirm_dialog(msg,
function() {
var btn = confirm_ometiff.data("clicked_button");
switch (btn) {
case "Create": // two options for the same button
case "Create New":
$.post( url, function() {
showActivities();
});
break;
case "Download":
window.location.href = download_ometiff;
break;
}
},
"Create OME-TIFF?",
dialog_opts,
null, 200
);
});

e.preventDefault();
return false;
});

});

</script>
Expand Down Expand Up @@ -389,40 +446,51 @@ <h1>
<button class="btn silver btn_edit" alt="e" title="edit">
<span></span>
</button>

{% comment %}
<img src="{% static "webclient/image/color_line12.png" %}" />
{% endcomment %}

</div>{% else %}

<h1 style="word-wrap: break-word;">{{ manager.image.name }}</h1>{% endif %}


<div style="position:relative">
<h2 class="data_heading_id" id='image_id' style="float:left">
Image ID: <strong>{{ manager.image.id }}</strong>
</h2>

<!-- open-image link -->
<button id="show_link_btn" class="btn silver btn_link" title="Link to this Image">
<span></span>
</button>
<div id="link_info_popup" class="info_popup" style="right:0px; top:30px; padding:4px; display:none">
<input type="text" size="30">
<img title="Close" src="{% static 'webgateway/img/close.gif' %}" />
</div>

<h2 class="data_heading_id" id='image_id'>
Image ID: <strong>{{ manager.image.id }}</strong>
<!-- open-image link -->
<button id="show_link_btn" class="btn silver btn_link" title="Link to this Image">
<span></span>
</button>
<div id="link_info_popup" class="info_popup" style="right:0px; top:30px; padding:4px; display:none">
<input type="text" size="30">
<img title="Close" src="{% static 'webgateway/img/close.gif' %}" />
</div>
</h2>


<!-- download options -->
<span id="download_dropdown">
<button id="show_download_dropdown" class="btn silver btn_download" title="Download Image as...">
<span></span>
</button>
<ul class="dropdown">
{% if manager.image.countArchivedFiles %}
<li>
<a id="download-origfile" href="{% url archived_files manager.image.id %}"
title="Download {{ manager.image.countArchivedFiles }} Archived file{{ manager.image.countArchivedFiles|pluralize:'s (zip)' }}">
Archived file{{ manager.image.countArchivedFiles|pluralize:'s (zip)' }}</a>
</li>
{% endif %}
<li>
<a id="create-ometiff" href="{% url ome_tiff_script manager.image.id %}"
title="Create OME-TIFF File for Download">OME-TIFF</a>
</li>
<li id="download-jpeg"><a href="{% url web_render_image_download manager.image.id %}" title="Download as JPEG">JPEG</a></li>
</ul>
</span>
</div>

<div style="clear:both"></div>
<div style="padding-bottom:6px; position:relative">

{% if manager.image.countArchivedFiles %}
<div style="float:right; top:30px; padding:4px">
<a href="{% url archived_files manager.image.id %}">
<img src="{% static "webclient/image/nuvola_download_manager16.png" %}"
title="Download {{ manager.image.countArchivedFiles }} Archived file{{ manager.image.countArchivedFiles|pluralize:'s (zip)' }}"/>
</a>
</div>
{% endif %}


<button class="btn silver btn_text" href="#" onclick="return openPopup('{% url web_image_viewer manager.image.id %}')"
title="Open full image viewer in new window">
<span>
Expand Down
6 changes: 6 additions & 0 deletions components/tools/OmeroWeb/omeroweb/webclient/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@
url( r'^(?:(?P<share_id>[0-9]+)/)?render_image_region/(?P<iid>[0-9]+)/(?P<z>[0-9]+)/(?P<t>[0-9]+)/$', webgateway.render_image_region, name="web_render_image_region"),
url( r'^(?:(?P<share_id>[0-9]+)/)?render_birds_eye_view/(?P<iid>[^/]+)/(?:(?P<size>[^/]+)/)?$', webgateway.render_birds_eye_view, name="web_render_birds_eye_view"),
url( r'^(?:(?P<share_id>[0-9]+)/)?render_image/(?P<iid>[^/]+)/(?:(?P<z>[^/]+)/)?(?:(?P<t>[^/]+)/)?$', webgateway.render_image, name="web_render_image"),
url( r'^(?:(?P<share_id>[0-9]+)/)?render_image_download/(?P<iid>[^/]+)/(?:(?P<z>[^/]+)/)?(?:(?P<t>[^/]+)/)?$',
webgateway.render_image, {'download':True}, name="web_render_image_download"),
url( r'^(?:(?P<share_id>[0-9]+)/)?img_detail/(?P<iid>[0-9]+)/$', views.image_viewer, name="web_image_viewer"),
url( r'^(?:(?P<share_id>[0-9]+)/)?imgData/(?P<iid>[0-9]+)/$', webgateway.imageData_json, name="web_imageData_json"),
url(r'^(?:(?P<share_id>[0-9]+)/)?render_row_plot/(?P<iid>[^/]+)/(?P<z>[^/]+)/(?P<t>[^/]+)/(?P<y>[^/]+)/(?:(?P<w>[^/]+)/)?$', webgateway.render_row_plot, name="web_render_row_plot"),
Expand Down Expand Up @@ -131,6 +133,10 @@
url( r'^script_run/(?P<scriptId>[0-9]+)/$', views.script_run, name='script_run' ), # runs the script - parameters in POST
url( r'^get_original_file/(?:(?P<fileId>[0-9]+)/)?$', views.get_original_file, name="get_original_file"), # for stderr, stdout etc

# ome_tiff_script: generate OME-TIFF and attach to image (use script service). Must be POST
url( r'^ome_tiff_script/(?P<imageId>[0-9]+)/$', views.ome_tiff_script, name='ome_tiff_script' ),
url( r'^ome_tiff_info/(?P<imageId>[0-9]+)/$', views.ome_tiff_info, name='ome_tiff_info' ),

# ping OMERO server to keep session alive
url( r'^keepalive_ping/$', views.keepalive_ping, name="keepalive_ping"),

Expand Down
60 changes: 54 additions & 6 deletions components/tools/OmeroWeb/omeroweb/webclient/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2108,7 +2108,7 @@ def activities(request, conn=None, **kwargs):
obj_data['browse_url'] = getObjectUrl(conn, v)
if v.isLoaded() and hasattr(v, "file"):
#try:
mimetypes = {'image/png':'png', 'image/jpeg':'jpeg', 'image/tiff': 'tiff'}
mimetypes = {'image/png':'png', 'image/jpeg':'jpeg', 'text/plain': 'text'}
if v.file.mimetype.val in mimetypes:
obj_data['fileType'] = mimetypes[v.file.mimetype.val]
obj_data['fileId'] = v.file.id.val
Expand Down Expand Up @@ -2470,15 +2470,47 @@ def script_run(request, scriptId, conn=None, **kwargs):
continue

logger.debug("Running script %s with params %s" % (scriptName, inputMap))
rsp = run_script(request, conn, sId, inputMap, scriptName)
return HttpResponse(simplejson.dumps(rsp), mimetype='json')


@login_required(setGroupContext=True)
def ome_tiff_script(request, imageId, conn=None, **kwargs):
"""
Uses the scripting service (Batch Image Export script) to generate OME-TIFF for an
image and attach this as a file annotation to the image.
Script will show up in the 'Activities' for users to monitor and download result etc.
"""
#if not request.method == 'POST':
# return HttpResponse("Need to use POST")

scriptService = conn.getScriptService()
sId = scriptService.getScriptID("/omero/export_scripts/Batch_Image_Export.py")

imageIds = [long(imageId)]
inputMap = {'Data_Type': wrap('Image'), 'IDs': wrap(imageIds)}
inputMap['Format'] = wrap('OME-TIFF')
rsp = run_script(request, conn, sId, inputMap, scriptName='Create OME-TIFF')
return HttpResponse(simplejson.dumps(rsp), mimetype='json')


def run_script(request, conn, sId, inputMap, scriptName='Script'):
"""
Starts running a script, adding details to the request.session so that it shows up
in the webclient Activities panel and results are available there etc.
"""
request.session.modified = True
scriptService = conn.getScriptService()
try:
handle = scriptService.runScript(sId, inputMap, None, conn.SERVICE_OPTS)
# E.g. ProcessCallback/4ab13b23-22c9-4b5f-9318-40f9a1acc4e9 -t:tcp -h 10.37.129.2 -p 53154:tcp -h 10.211.55.2 -p 53154:tcp -h 10.12.1.230 -p 53154
jobId = str(handle)
status = 'in progress'
request.session['callback'][jobId] = {
'job_type': "script",
'job_name': scriptName,
'start_time': datetime.datetime.now(),
'status':'in progress'}
'status':status}
request.session.modified = True
except Exception, x:
jobId = str(time()) # E.g. 1312803670.6076391
Expand All @@ -2500,9 +2532,25 @@ def script_run(request, scriptId, conn=None, **kwargs):
'status':status,
'Message': message,
'error':error}
request.session.modified = True
# we return this, although it is now ignored (script window closes)
return HttpResponse(simplejson.dumps({'status': status, 'error': error}), mimetype='json')
return {'status': status, 'error': error}

return HttpResponse(simplejson.dumps({'jobId': jobId, 'status':'in progress'}), mimetype='json')
return {'jobId': jobId, 'status': status}

@login_required()
@render_response()
def ome_tiff_info(request, imageId, conn=None, **kwargs):
"""
Query to see if we have an OME-TIFF attached to the image (assume only 1, since Batch Image Export will delete old ones)
"""
# Any existing OME-TIFF will appear in list
links = list( conn.getAnnotationLinks("Image", [imageId], ns=omero.constants.namespaces.NSOMETIFF) )
rv = {}
if len(links) > 0:
links.sort(key=lambda x: x.getId(), reverse=True) # use highest ID === most recent
annlink = links[0]
created = annlink.creationEventDate()
annId = annlink.getChild().getId()
from omeroweb.webgateway.templatetags.common_filters import ago
download = reverse("download_annotation", args=[annId])
rv = {"created": str(created), "ago": ago(created), "id":annId, "download": download}
return rv # will get returned as json by default
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,7 @@

#activities_panel {
width:400px;
overflow-y: auto;
}

#activities_spinner, #basket_spinner {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,33 @@
def hash(value, key):
return value[key]

@register.filter
def ago(value):
""" Formats a datetime.datetime object as time Ago. E.g. '3 days 2 hours 10 minutes' """
try:
ago = datetime.datetime.now() - value
except TypeError:
return str(value)
def plurals(val):
return val != 1 and "s" or ""
hours, remainder = divmod(ago.seconds, 3600)
mins, secs = divmod(remainder, 60)
if ago.days >= 365:
years = ago.days / 365
return "%s year%s" % (years, plurals(years))
if ago.days > 28:
months = ago.days / 30
return "%s month%s" % (months, plurals(months))
if ago.days > 0:
return "%s day%s" % (ago.days, plurals(ago.days))
if hours > 0:
return "%s hour%s" % (hours, plurals(hours))
if mins > 1:
return "%s minutes" % (mins)
if mins == 1:
return "a minute"
return "less than a minute"

@register.filter
def truncateafter(value, arg):
"""
Expand Down
4 changes: 4 additions & 0 deletions components/tools/OmeroWeb/omeroweb/webgateway/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,10 @@ def render_image (request, iid, z=None, t=None, conn=None, **kwargs):
webgateway_cache.setImage(request, server_id, img, z, t, jpeg_data)

rsp = HttpResponse(jpeg_data, mimetype='image/jpeg')
if 'download' in kwargs and kwargs['download']:
rsp['Content-Type'] = 'application/force-download'
rsp['Content-Length'] = len(jpeg_data)
rsp['Content-Disposition'] = 'attachment; filename=%s.jpg' % (img.getName().replace(" ","_"))
return rsp

@login_required()
Expand Down