Skip to content

Instantly share code, notes, and snippets.

@imoutsatsos
Created October 10, 2018 14:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imoutsatsos/ca662a31af429fcadd120a80d2f50c35 to your computer and use it in GitHub Desktop.
Save imoutsatsos/ca662a31af429fcadd120a80d2f50c35 to your computer and use it in GitHub Desktop.
Jenkins scriptlet: Generates parametrized HTML from a image grid OpenSeadragon template
/*** BEGIN META {
"name" : "imageGalleryFromtemplate",
"comment" : "Generate parametrized HTML from a image grid Openseadragon template",
"parameters" : [ 'vTemplateURLPath','vOutfolder','vIMAGELIST_URL','vIMAGE_OBJECTS','vTEST_IMAGES','vIMAGE_GALLERY','vPRIMARY_IMAGE_LIST','vJOB_PATH','vIMAGE_ADJUSTMENTS','vBUILD_LABEL'],
"core": "1.596",
"authors" : [
{ name : "Ioannis K. Moutsatsos" }
]
} END META**/
/*
Template binding requires two comma separated lists of param names and values. They must be of same size and match order
Depends on 2 property files : project.properties and the Cantaloupe Image server properties file
Note:'vIMAGE_GALLERY' is the layout strategy like '6,columnsFirst'
*/
import java.net.URLEncoder;
def templateURLPath=vTemplateURLPath
def outfolder =vOutfolder
def PRIMARY_IMAGE_LIST=vPRIMARY_IMAGE_LIST
def IMAGELIST_URL=vIMAGELIST_URL
def IMAGE_OBJECTS=vIMAGE_OBJECTS
def TEST_IMAGES=vTEST_IMAGES
def IMAGE_GALLERY=vIMAGE_GALLERY
def IMAGE_ADJUSTMENTS=vIMAGE_ADJUSTMENTS
def JOB_PATH=vJOB_PATH //needed for finding project.properties
def ext='html'
/*
creates an array of imageTile URLs and loads it into the i2v(images to view) HTML element
hard coded properties for Cantaloupe Image Server
*/
def _IMAGE_COLOR=0
def _IMAGE_COLORINTENSITY=1
def _IMAGE_PATH=2
def _IMAGE_LABEL=3
def displayRows=0
def imgTiles=''
def imageLabels=''
def imgCount=0 //number of images to retrieve
def imgAdjustments=getImageAdjustmentsMap(IMAGE_ADJUSTMENTS)
def imgColorSpec=getImageObjectMap(IMAGE_OBJECTS, IMAGE_ADJUSTMENTS)
props=new Properties()
propertiesFile=new File("${JOB_PATH}/buildProps/project.properties")
assert propertiesFile.exists()
props.load(propertiesFile.newDataInputStream())
baseUrl=''
normalizedBaseUrl=props.getProperty('normalizedBaseUrl') //'http://nrusca-sd189.nibr.novartis.net:8182/iiif/2/'
rawBaseUrl=props.getProperty('rawBaseUrl') //'http://nrusca-swp4106.nibr.novartis.net:8182/iiif/2/'
replaceMap=evaluate(props.getProperty('alt_path_prefix'))
alt_path_prefix=replaceMap.keySet()
if (imgAdjustments.normalize){
baseUrl=normalizedBaseUrl
}else{
baseUrl=rawBaseUrl
}
encodedPathSeparator='%2F'
tsPath=encodedPathSeparator
tsPostfix='/info.json'
/*
Determine the number of the gallery grid rows from the number of selected object types
*/
if (IMAGE_OBJECTS.contains(',')){
displayRows=IMAGE_OBJECTS.split(',').size()
}else{
displayRows=1
}
if (TEST_IMAGES!='' ){
imageNames=stripColorInfo(TEST_IMAGES.split(',') as List, _IMAGE_PATH).collect{it.replace('\\\\','/')}
imageMeta=stripColorInfo(TEST_IMAGES.split(',') as List, _IMAGE_LABEL)
imgCount=imageMeta.size()
imageLabels=imageMeta.join(',')
pathPrefix= imageServerPrefix(imageNames[0] as String,alt_path_prefix as List)
imgTiles=imageNames.collect{baseUrl+tsPath+encodedPathSeparator+ URLEncoder.encode( it.replace('\\','/').replaceAll("(?i)"+pathPrefix.replace('$','\\$'), replaceMap[pathPrefix]),"UTF-8")+tsPostfix}.join(',')
}//end if
/*
Create a default file name for the text file
Name from Template file name by removing the case insensitive string 'template'
and adding the extension
*/
textName=templateURLPath.split('/').last().replaceAll("(?i)template",'')
/*
prepare template binding parameters
create paired lists of template binding parameter-names and parameter-values
*/
def templateParam='primaryImageListUrl,primaryImageListNumber,gridSize,fillStrategy'
def paramValue="""${IMAGELIST_URL.split('artifact')[0]},${PRIMARY_IMAGE_LIST.split('#')[1]},$IMAGE_GALLERY"""
def bindParamsNames=templateParam.tokenize(',')
def bindParamsVals=paramValue.tokenize(',')
bindParamsNames.add('galleryLabel')
bindParamsVals.add("$BUILD_LABEL")
bindParamsNames.add('adjustments')
bindParamsVals.add(imgAdjustments)
bindParamsNames.add('imgObjectColors')
bindParamsVals.add(imgColorSpec)
bindParamsNames.add('imgCount')
bindParamsVals.add(imgCount)
bindParamsNames.add('osdJs')
bindParamsVals.add("openseadragon-bin-2.4.0")
templateBinding=prepareBinding(bindParamsNames,bindParamsVals, imgTiles, imageLabels)
//make directory if does not exist
out= new File(outfolder)
out.mkdirs()
writeHTML(templateBinding,templateURLPath,"$outfolder/$textName$ext")
/*
find appropriate replacement prefix
by reviewing image tile path against acceptable image server prefixes
*/
def imageServerPrefix(String imageName, List altPathPrefix){
path_prefix='MissingImageServerPath'
normPath= imageName.replaceAll('$','\\$').replace('\\','/').toLowerCase()
altPathPrefix.each{apx->
if (normPath.startsWith(apx.toLowerCase())){
path_prefix=apx
}
}
return path_prefix
}
/*
a utility method for striping color/intensity infor
from a list of color/intensity annotated image lists
Returns a clean list of image names
*/
def stripColorInfo (List imageColorInfoList, imgConstant){
noColorInfoImages=[]
if (imageColorInfoList[0].class==String){
noColorInfoImages=imageColorInfoList.collect{it.split(':')[imgConstant]}
}else{
imageColorInfoList.each{imgCol->
noColorInfoImages.add(imgCol.collect{it.split(':')[imgConstant]})//the 3rd list element should contain the image name
}
} //end else
return noColorInfoImages
} //end stripColorInfo
/* returns image object properties map
imageObjects are returned from IMAGE_OBJECTS control and
codedAdjustments from IMAGE_ADJUSTMENTS: value is like: 0,#ff0000,0.3,#00ff00,0.3,#0000ff,0,1,true,3,true
*/
def getImageObjectMap(imageObjects,codedAdjustments) {
objects = imageObjects.split(',')
objColorInfo=codedAdjustments.split(',')[0..(objects.size()*2)-1]
g= objColorInfo.collate(2)
objMap = []
objects.eachWithIndex { v, ind ->
thisObj = [name: v, color:g[ind][1], opacity: g[ind][0]]
objMap.add(thisObj)
}
return objMap
}
/*
a function to configure the template Binding from user inputs
and some required custom keys
*/
def Map prepareBinding(ArrayList bindParamsNames, ArrayList bindParamsVals, String imgTiles, String imageLabels){
def templateBinding=[:]
assert bindParamsNames.size()==bindParamsVals.size()
v=0
bindParamsNames.each{
templateBinding.put("$it" as String, bindParamsVals[v])
v++
}
//add some custom bindings
templateBinding.put('imgTiles',imgTiles)
templateBinding.put('imageLabels',imageLabels)
return templateBinding
}
/*
a function to write an HTML file from the template
*/
def void writeHTML(Map binding, String templateURLPath, String outputFileName){
def theTemplateURL=templateURLPath.toURL()
def theTemplate=theTemplateURL.getText()
def reportHtml=new File(outputFileName)
def reportHtmlWriter= reportHtml.newWriter(false)
def engine = new groovy.text.GStringTemplateEngine()
arrayTemplate = engine.createTemplate(theTemplate)
reportHtmlWriter<< arrayTemplate.make(binding)
reportHtmlWriter.flush()
reportHtmlWriter.close()
println "Generated file: ${reportHtml.canonicalPath}"
}
/*
returns a map of the image adjustment values
encoded value are now labelled for easy ID:
0.3,#3dff00,0.3,#0000ff,0.3,#ff0000,set_intensitNorm,brightness,0,contrast,1,getOverlay,3,lastLayout:6;columnsFirst,freezeLayout
--OR--
0.3,#3dff00,0.3,#0000ff,0.3,#ff0000,set_intensitNorm,brightness,0,contrast,1,getOverlay,3,false
*/
def getImageAdjustmentsMap(imageAdjustments){
theMap=[:]
adjustments=imageAdjustments.tokenize(',')
theMap.put('normalize',normalizeFlag=(adjustments.contains('set_intensitNorm'))?true:false)
theMap.put('overlay',overlayFlag=(adjustments.contains('getOverlay'))?true:false)
theMap.put('brightness', adjustments[(adjustments.findIndexValues{it=='brightness'}[0] as int)+1])
theMap.put('contrast', adjustments[(adjustments.findIndexValues{it=='contrast'}[0] as int)+1])
if (overlayFlag){
theMap.put('imagesPerOverlay',adjustments[(adjustments.findIndexValues{it=='getOverlay'}[0] as int)+1])
}else{
theMap.put('imagesPerOverlay',vIMAGE_OBJECTS.tokenize(',').size())
}
if (adjustments.contains('freezeLayout')){
layLastIndex=adjustments.findIndexValues{it.startsWith('lastLayout')}
theMap.put('displayRows',adjustments[layLastIndex][0].split(':')[1].split(';')[0])
theMap.put('layoutStrategy',(adjustments[layLastIndex][0].split(':')[1].split(';')[1]=='rowsFirst')?'rowsFirst':'columnsFirst')
}
println theMap
return theMap
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment