Created
October 10, 2018 14:45
-
-
Save imoutsatsos/ca662a31af429fcadd120a80d2f50c35 to your computer and use it in GitHub Desktop.
Jenkins scriptlet: Generates parametrized HTML from a image grid OpenSeadragon template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*** 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