Skip to content

Instantly share code, notes, and snippets.

@bdunnette
Last active February 24, 2020 18:05
Show Gist options
  • Save bdunnette/51cc4127a5cd1e1877e58fbd649c1d19 to your computer and use it in GitHub Desktop.
Save bdunnette/51cc4127a5cd1e1877e58fbd649c1d19 to your computer and use it in GitHub Desktop.
import sys
import os
from zipfile import ZipFile
from csv import DictReader
from pathlib import Path
from datetime import date
from jinja2 import Template
bootstrap_version = "3.4.1"
jquery_version = "3.4.1"
leaflet_version = "1.6.0"
leaflet_fullscreen_version = "1.6.0"
copyright_holder = "Regents of the University of Minnesota"
copyright_year = date.today().year
missing_image_url="//upload.wikimedia.org/wikipedia/commons/thumb/5/53/Font_Awesome_5_regular_clock.svg/240px-Font_Awesome_5_regular_clock.svg.png"
index_template = Template("<html><head>"
"<meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'>"
"<link rel='stylesheet' href='//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/{{bootstrap_version}}/css/bootstrap.min.css' />"
"<script src='//cdnjs.cloudflare.com/ajax/libs/jquery/{{jquery_version}}/jquery.min.js' ></script>"
"<title>{{title}}</title></head>"
"<body><div class='container'>"
"<div class='page-header'><h1>{{title}}</h1></div>"
"<div class='row'>{% for slide in slides %}"
"<div class='col-md-3 col-sm-6 col-xs-12'>"
"<div class='panel panel-default' id='{{loop.index}}'>"
"<div class='panel-heading'>"
"<span class='panel-title'><strong>{{slide['Block ID']}} {{slide['Stain']}}</strong></span>"
"</div><div class='panel-body'>"
"<a href='{{slide['stem']}}.html'>"
"<img src='{{slide['stem']}}/0/0/0.jpg' class='img-thumbnail'></a>"
"</div></div></div>"
"{% endfor %}</div></div>"
"<script>$('img').on('error', function() {$(this).attr('src', '{{missing_image_url}}').parent().attr('href','#0');});</script>"
"</body></html>")
slide_template = Template("<!DOCTYPE html><html><head><meta charset='utf-8'>"
"<meta name='viewport' content='width=device-width'>"
"<link rel='stylesheet' href='//cdnjs.cloudflare.com/ajax/libs/leaflet/{{leaflet_version}}/leaflet.css' />"
"<link rel='stylesheet' href='//cdnjs.cloudflare.com/ajax/libs/leaflet.fullscreen/{{leaflet_fullscreen_version}}/Control.FullScreen.css' />"
"<script src='//cdnjs.cloudflare.com/ajax/libs/jquery/{{jquery_version}}/jquery.min.js' ></script>"
"<script src='//cdnjs.cloudflare.com/ajax/libs/leaflet/{{leaflet_version}}/leaflet.js' ></script>"
"<script src='//cdnjs.cloudflare.com/ajax/libs/leaflet.fullscreen/{{leaflet_fullscreen_version}}/Control.FullScreen.min.js'></script>"
"<style>.leaflet-container {background: #FFF;}</style>"
"<title>{{slide['Case Number']}} {{slide['Block ID']}} {{slide['Stain']}}</title></head>"
"<body style='margin:0;'><div id='map'></div>"
"<script>$(document).ready(function () {"
"$('#map').css({height: $(window).height() + 'px'});"
"var map = new L.map('map', {fullscreenControl: true, fullscreenControlOptions: {position: 'topleft'}});"
"var slideUrl = '{{slide['stem']}}/{z}/{y}/{x}.jpg';"
"slide = L.tileLayer(slideUrl, {minZoom: 0, maxZoom: {{max_zoom}}, noWrap: true, "
"errorTileUrl: '{{slide['stem']}}/blank.png', "
"attribution: 'Images &copy; {{copyright_year}} {{copyright_holder}}'});"
"map.addLayer(slide);map.setView(new L.LatLng(0, 0), 2);map.attributionControl.setPrefix('');"
"$(window).resize(function () {$('#map').css({height: $(window).height() + 'px'});});"
"});</script>"
"</body></html>")
def main():
files_to_parse = sys.argv[1:]
for f in files_to_parse:
print("Reading cases from %s" % f)
cases = []
with open(f) as csvfile:
reader = DictReader(csvfile)
for row in reader:
case_dict = dict(row)
image_location = Path(case_dict['Image Location'])
# print(image_location)
# print(image_location.parts, image_location.name,
# image_location.suffix, image_location.stem)
# slide_id = case_dict['Image ID']
slide_id = image_location.stem
case_dict['stem'] = image_location.stem
print(case_dict)
cases.append(case_dict)
zipfile_name = "{}.zip".format(slide_id)
if os.path.exists(zipfile_name):
try:
with ZipFile(zipfile_name, 'r') as z:
dirs = list(set([os.path.dirname(x)
for x in z.namelist()]))
# Sort the zipfile directories in reverse, so we get the highest-zoom directories first
last_dir = sorted(dirs, reverse=True)[0]
# Get the second part of the path, which is the zoom level - e.g. "12345/8/99" -> "8"
max_zoom = os.path.split(
os.path.split(last_dir)[0])[1]
except:
max_zoom = 8
else:
max_zoom = 8
print("max_zoom=%s" % max_zoom)
slide_html = slide_template.render(
slide=case_dict, max_zoom=max_zoom, copyright_year=copyright_year, copyright_holder=copyright_holder,
jquery_version=jquery_version, leaflet_version=leaflet_version, leaflet_fullscreen_version=leaflet_fullscreen_version)
# print(slide_html)
with open("./{}.html".format(slide_id), "w") as slide_file:
print("Writing {}.html...".format(slide_id))
slide_file.write(slide_html)
index_html = index_template.render(
title=cases[0]['Case Number'], slides=cases, bootstrap_version=bootstrap_version, jquery_version=jquery_version, missing_image_url=missing_image_url)
# print(index_html)
with open("./index.html", "w") as index_file:
print("Writing index.html...")
index_file.write(index_html)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment