-
-
Save coronin/5f62753a8978460680a7 to your computer and use it in GitHub Desktop.
for parsing micro-manager metadata
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
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |
<title>MM Metadata Viewer</title> | |
<style type="text/css" media="screen"><!-- | |
body{margin:25px;padding:0;font-family:Arial,Helvetica,sans-serif;font-size:100%} | |
article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block} | |
h1,h2,h3,h4{font-weight:700} | |
h1{font-size:2em} | |
h2{font-size:1.5em} | |
h3{font-size:1.2em} | |
h4{font-size:1em} | |
a{text-decoration:underline} | |
a:link{color:#00E} | |
a:visited{color:#551A8B} | |
a:active{color:#E00} | |
a:active,a:hover{outline:0} | |
a img{border:none} | |
sub,sup{line-height:0} | |
--></style> | |
<link rel="stylesheet" href="jsontree.css"><!-- from https://github.com/jurka/jsontree --> | |
</head> | |
<body> | |
<h1>Micro-Manager Metadata Viewer <sup style="color:purple"> © Liang Cai</sup></h1> | |
<p> | |
<span id="action_area"><input type="file" id="fileInput" /> <input type="submit" value="view" id="view" /></span> | |
<span style="float:right;font-size:0.75em">Last updated on <script language="JavaScript" type="">document.write(document.lastModified)</script></span> | |
</p> | |
<div id="jsondata"><span style="color:red;background:yellow">For file size over 4M, do run it inside Chrome on a powerful computer.</span></div> | |
</body> | |
<script src="jquery-2.1.3.min.js"></script> | |
<script>window.jQuery || document.write('<script src="jquery-2.1.3.min.js"><\/script>')</script> | |
<script> | |
var DEBUG = false, mm_file, mm_html, mm_frames, timer_start, | |
NonShowKeys = ['UUID', | |
'UserName', | |
'Date', | |
'MetadataVersion', | |
'MicroManagerVersion', | |
'ROI', | |
'Prefix', | |
'Source', | |
'ComputerName', | |
'KeepShutterOpenChannels', | |
'KeepShutterOpenSlices', | |
'ChContrastMax', | |
'Directory', | |
'-TransposeMirrorX', | |
'-TransposeMirrorY', | |
'-TransposeXY', | |
'-Description', | |
'-Name', | |
'-Model', | |
'-Mode', | |
'-Initialize', | |
'-FocusWheel', | |
'-PixelType', | |
'-AnswerTimeout', | |
'-FanMode', | |
'-DelayBetweenCharsMs', | |
'-State', | |
'-Trigger', | |
'-Parity', | |
'-Verbose', | |
'-StopBits', | |
'-BaudRate', | |
'-Advanced | Snap Image Additional Delay (ms)', | |
'-VerticalClockVoltage', | |
'-SearchRange', | |
'-TransposeCorrection', | |
'-Camera', | |
'Core-SLM', | |
'-Delay_ms', | |
'-Handshaking', | |
'-FarLimit', | |
'-NearLimit', | |
'-Region of Interest', | |
'-OptAcquireMode', | |
'-OptAcquireMode Description', | |
'-1. Camera Information : | Type | Model | Serial No. |', | |
'-2. Camera Information : | Type | Model | Serial No. |', | |
'-DataBits', | |
'-FocusSensitivity', | |
'-TimeOut', | |
'Core-Galvo', | |
'Core-Focus', | |
'-Port', | |
'-Shutter Closing Time', | |
'-Shutter Opening Time', | |
'LightPath-Label', | |
'-KeepCleanTime', | |
'-Shutter TTL Value', | |
'-MaxSpeed', | |
'-VerticalSpeed', | |
'-CoolerMode', | |
'-NDSetting', | |
'-CCDTemperature', | |
'-CCDTemperatureSetPoint', | |
'SimpleAutofocus-', | |
'-ReadoutMode', | |
'-EMSwitch', | |
'-Busy', | |
'-Speed', | |
'-BaselineClamp', | |
'-Isolated Crop Mode', | |
'Core-ChannelGroup', | |
'Core-AutoShutter', | |
'Core-XYStage', | |
'-Shutter', | |
'-TimeoutMs', | |
'-FrameTransfer Help', | |
'-Voltage', | |
'-ActualInterval-ms', | |
'-SCurve', | |
'-StepSizeX_um', | |
'-StepSizeY_um', | |
'-Control', | |
'-Controller Info', | |
'InitialPositionList', | |
'Depth', | |
'PixelType', | |
'BitDepth', | |
'ChContrastMin', | |
'Width', | |
'Height', | |
'PixelAspect', | |
'IJType', | |
'GridRow', | |
'Comment', | |
'GridColumn', | |
'PixelSize_um', | |
'-ClosedPosition', | |
'-Exposure', | |
'-CCDTemperature Help', | |
'-FrameTransfer', | |
'OlympusHub-Version', | |
'Core-ImageProcessor', | |
'-Gain', | |
'-Pre-Amp-Gain', | |
'CustomIntervals_ms', | |
'ChColors', | |
'SlicePosition', | |
'AxisPositions', | |
'-ObjectiveTypeSetting', | |
'-Acceleration', | |
'PixelSizeUm', | |
'Binning', | |
'-ReadoutTime', | |
'-Advanced | Snap Image Timing Mode', | |
'-Binning', | |
'ElapsedTime-ms', | |
'Core-AutoFocus', | |
'-ContinuousMode', | |
'-Offset', | |
'Camera', | |
'-AD_Converter', | |
'-CountConvertWavelength', | |
'-Shutter (External)', | |
'-Shutter (Internal)', | |
'-SpuriousNoiseFilterThreshold', | |
'Interval_ms', | |
'XPositionUm', | |
'YPositionUm', | |
'Positions', | |
'PositionIndex', | |
'-CountConvert', | |
'-SpuriousNoiseFilterDescription', | |
'-SpuriousNoiseFilter', | |
'Slice', | |
'NextFrame', | |
'Frame', | |
'ChannelIndex', | |
'TransmittedLamp-Label', | |
'WaitInterval', | |
'-Position', | |
'CameraChannelIndex', | |
'-PiezoRange', | |
'-PiezoPosition', | |
'-Output_Amplifier', | |
'-CameraName', | |
'-TriggerMode', | |
'-SensorTemperature', | |
'-PixelReadoutRate', | |
'-CameraID', | |
'-PixelEncoding', | |
'-Overlap', | |
'-CurrentSoftware', | |
'-FanSpeed', | |
'-AccumulateCount', | |
'-CameraModel', | |
'-Sensitivity/DynamicRange', | |
'-TemperatureControl', | |
'-AuxiliaryOutSource (TTL I/O)', | |
'-FrameRateLimits', | |
'-SensorCooling', | |
'-CameraFirmware', | |
'-TemperatureStatus', | |
'-Ext (Exp) Trigger Timeout[ms]' | |
], | |
HighlightKeys = ['Slices', | |
'Frames', | |
'Channels' | |
]; | |
function check_obj(obj, parent_obj, keyNameClean) { | |
var keyNamePos = 0; | |
if (keyNameClean.indexOf('10-3') === 0) { | |
keyNamePos = keyNameClean.replace('10-3', '10~3').indexOf('-'); | |
} else if (keyNameClean.indexOf('Wheel-A') === 0) { | |
keyNamePos = keyNameClean.replace('Wheel-A', 'Wheel~A').indexOf('-'); | |
} else { | |
keyNamePos = keyNameClean.indexOf('-'); | |
} | |
if (keyNameClean === 'Slices' && typeof obj[keyNameClean] === 'number' && obj[keyNameClean] > 1) { | |
HighlightKeys.push('z-step_um'); // only works, if Slices preceeds z-step_um | |
HighlightKeys.push('SliceIndex'); | |
HighlightKeys.push('ZPositionUm'); | |
} else if (keyNameClean === 'Frames' && typeof obj[keyNameClean] === 'number' && obj[keyNameClean] > 1) { | |
HighlightKeys.push('FrameIndex'); | |
} else if (keyNameClean === 'Channels' && typeof obj[keyNameClean] === 'number' && obj[keyNameClean] > 1) { | |
HighlightKeys.push('Channel'); | |
} | |
if ( HighlightKeys.indexOf(keyNameClean) > -1 ) { | |
return 2; | |
} | |
if ( NonShowKeys.indexOf(keyNameClean) > -1 || | |
(keyNamePos > -1 && NonShowKeys.indexOf( keyNameClean.substr(keyNamePos) ) > -1) || | |
(keyNamePos > -1 && NonShowKeys.indexOf( keyNameClean.substr(0, keyNamePos+1) ) > -1) | |
) { | |
DEBUG && console.log(keyNameClean); | |
return 0; | |
} | |
if (keyNameClean.indexOf('AndorLaserCombiner-') === 0) { | |
DEBUG && console.log(keyNameClean); | |
return 0; | |
} | |
if (keyNameClean.indexOf('CSUX-') === 0) { | |
DEBUG && console.log(keyNameClean); | |
return 0; | |
} | |
if (obj[keyNameClean] === null) { | |
DEBUG && console.log(keyNameClean); | |
return 0; | |
} | |
if (keyNameClean === 'Summary') { | |
var ele_fourUpID = parent_obj.parent().parent().parent().attr('id'); | |
if (!ele_fourUpID) { | |
return 0; | |
} else if (ele_fourUpID === 'jsondata') { | |
return 2; | |
} | |
} | |
if (typeof obj[keyNameClean] === 'string' && obj[keyNameClean] === 'Default' && !parent_obj.hasClass('array')) { | |
DEBUG && console.log(keyNameClean); | |
return 0; | |
} | |
if (keyNameClean.indexOf('FrameKey-') === 0) { | |
return 9; | |
} | |
return 1; | |
} | |
function update_timer() { | |
setTimeout(function () { | |
$('#text_timer').text( 'time spent: ' + Math.round(100*(performance.now()-timer_start))/100 + 'ms' ); | |
}, 10); | |
} | |
function jsontree_render(obj, parent_obj) { | |
var key, node_state, highLight, coma, aroval, | |
ic = 0, | |
count = 0, | |
key_array = new Array( obj.length ); | |
for (key in obj) { | |
if (!key || !obj.hasOwnProperty(key)) { | |
continue; | |
} | |
key_array[count] = key; | |
count += 1; | |
} | |
for (ic; ic < count; ic += 1) { | |
key = key_array[ic]; | |
node_state = check_obj(obj, parent_obj, key); | |
highLight = ''; | |
coma = ''; | |
if (ic < count-1) { | |
coma = ','; | |
} | |
if (!node_state) { | |
continue; | |
} else if (node_state === 2) { | |
highLight = ' style="background:cyan"'; | |
} | |
if (obj[key] === null) { | |
mm_html.push('<li><span class="key"'+highLight+'>'+key+':</span><span class="null"> null </span>'+coma+'</li>'); | |
} else if (typeof obj[key] === 'boolean') { | |
mm_html.push('<li><span class="key"'+highLight+'>'+key+':</span><span class="boolean">'+obj[key]+'</span>'+coma+'</li>'); | |
} else if (typeof obj[key] === 'number') { | |
mm_html.push('<li><span class="key"'+highLight+'>'+key+':</span><span class="number">'+obj[key]+'</span>'+coma+'</li>'); | |
} else if (typeof obj[key] === 'string') { | |
mm_html.push('<li><span class="key"'+highLight+'>'+key+':</span><span class="string">"'+obj[key]+'"</span>'+coma+'</li>'); | |
} else if ( $.isArray(obj[key]) ) { | |
aroval = Math.round( 1000*performance.now() ); | |
mm_html.push('<li><span class="key"'+highLight+'>'+key+':</span><span class="fold">[</span><ul class="array" id="ul'+aroval+'"></ul><span>]</span>'+coma+'</li>'); | |
parent_obj.append( mm_html.join('') ); | |
mm_html = []; | |
jsontree_render(obj[key], $('#ul'+aroval)); | |
} else { | |
aroval = Math.round( 1000*performance.now() ); | |
if (node_state === 9) { | |
mm_frames.push(aroval); | |
} | |
mm_html.push('<li><span class="key"'+highLight+'>'+key+':</span><span class="fold" id="span'+aroval+'">{</span><ul class="object" id="ul'+aroval+'"></ul><span>}</span>'+coma+'</li>'); | |
parent_obj.append( mm_html.join('') ); | |
mm_html = []; | |
jsontree_render(obj[key], $('#ul'+aroval)); | |
} | |
} | |
if (mm_html.length > 0) { | |
parent_obj.append( mm_html.join('') ); | |
mm_html = []; | |
} | |
update_timer(); | |
return ic; | |
} | |
function receivedText() { | |
console.timeEnd('load'); | |
update_timer(); | |
$('#jsondata').html(''); | |
mm_frames = []; | |
try { | |
console.time('parse'); | |
var mm_json = $.parseJSON( mm_file.result ); | |
console.timeEnd('parse'); | |
update_timer(); | |
console.time('paint'); | |
// inspired by jsontree.js | |
$('#jsondata').append('<ul class="jsontree"></ul>'); | |
mm_html = []; | |
jsontree_render([mm_json], $('#jsondata ul.jsontree')); | |
console.timeEnd('paint'); | |
update_timer(); | |
console.time('animate'); | |
$(document).on('click', 'ul.jsontree span.fold', function (event) { | |
$(this).addClass('folded').next().slideUp(); | |
event.preventDefault(); | |
}); | |
$(document).on('click', 'ul.jsontree span.fold.folded', function (event) { | |
$(this).removeClass('folded').next().slideDown(); | |
event.preventDefault(); | |
}); | |
var a_frame = null; | |
while (mm_frames.length > 0) { | |
a_frame = mm_frames.shift(); | |
$('#span'+a_frame).addClass('folded'); | |
$('#ul'+a_frame).css({'display': 'none'}); | |
} | |
console.timeEnd('animate'); | |
update_timer(); | |
$('#text_timer').css({'color': 'blue'}); | |
} catch (err) { | |
$('#jsondata').text(mm_file.result); | |
alert(err); | |
} | |
return; | |
} | |
function upload_file(file_element) { | |
if ( !file_element.files ) { | |
alert('This browser does not seem to support the "files" property.'); | |
} else if ( !file_element.files[0] ) { | |
alert('Please select a file before clicking "view"'); | |
} else { | |
console.time('load'); | |
var fi = file_element.files[0]; | |
DEBUG && console.log(fi.name); | |
$('#action_area').html(fi.name + '<span style="color:green;padding-left:2em;font-size:0.8em" id="text_timer">...</span>'); | |
mm_file = new FileReader(); | |
mm_file.onload = receivedText; | |
mm_file.readAsText(fi); | |
} | |
return; | |
} | |
$(document).ready(function () { | |
$('#view').on('click', function (event) { | |
if (!window.File || !window.FileReader || !window.FileList || !window.Blob) { | |
alert('The File APIs are not fully supported in this browser.'); | |
return false; | |
} | |
timer_start = performance.now(); | |
upload_file( document.getElementById('fileInput') ); | |
event.preventDefault(); | |
}); | |
}); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ready for public preview