Create a gist now

Instantly share code, notes, and snippets.

@coronin /mm-json.html Secret
Last active Aug 29, 2015

What would you like to do?
for parsing micro-manager metadata
<!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">&nbsp;&copy; 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>
Owner

coronin commented Dec 28, 2014

ready for public preview

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment