Permalink
Browse files

Adding parserMRC and test pages

  • Loading branch information...
emilysperanza committed Mar 23, 2014
1 parent 6e14210 commit 25ea88e2a1fe8f03970cd5f92aeae66d717d8b44
View
@@ -40,6 +40,7 @@ goog.require('X.parserLBL');
goog.require('X.parserLUT');
goog.require('X.parserMGZ');
goog.require('X.parserNII');
goog.require('X.parserMRC');
goog.require('X.parserNRRD');
goog.require('X.parserOBJ');
goog.require('X.parserOFF');
@@ -364,6 +365,8 @@ X.loader.extensions = {
'STL': [X.parserSTL, null],
'VTK': [X.parserVTK, null],
'TRK': [X.parserTRK, null],
'MRC': [X.parserMRC, null],
'ST': [X.parserMRC, null],
// FSM, INFLATED, SMOOTHWM, SPHERE, PIAL and ORIG are all freesurfer meshes
'FSM': [X.parserFSM, null],
'INFLATED': [X.parserFSM, null],
View
@@ -0,0 +1,359 @@
/*
*Parser for MRC files
*
*/
// provides
goog.provide('X.parserMRC');
// requires
goog.require('X.event');
goog.require('X.object');
goog.require('X.parser');
goog.require('X.triplets');
goog.require('goog.vec.Mat3');
goog.require('goog.vec.Mat4');
goog.require('Zlib.Gunzip');
/**
* Create a parser for .mrc files.
*
* @constructor
* @extends X.parser
*/
X.parserMRC = function() {
//
// call the standard constructor of X.parser
goog.base(this);
//
// class attributes
/*
* @inheritDoc
* @const
*/
this._classname = 'parserMRC';
};
// inhert from X.parser
goog.inherits(X.parserMRC, X.parser);
/**
* @inheritDoc
*/
X.parserMRC.prototype.parse = function(container, object, data, flag) {
X.TIMER(this._classname + '.parse');
var _data = data;
// parse the byte stream
var MRI = this.parseStream(_data);
// min and max intensities
var min = MRI.min;
var max = MRI.max;
//get dimsensions
var _dimensions = [MRI.nx, MRI.ny, MRI.nz];
object._dimensions = _dimensions
//get pixel spacing = xlen/mx
var spacingX = MRI.xlen / MRI.mx;
var spacingY = MRI.ylen / MRI.my;
var spacingZ = MRI.zlen / MRI.mz;
object._spacing = [ spacingX, spacingY, spacingZ ];
// attach the scalar range to the volume
object._min = object._windowLow = min;
object._max = object._windowHigh = max;
// set the default threshold
if (object._lowerThreshold == -Infinity) {
object._lowerThreshold = min;
}
if (object._upperThreshold == Infinity) {
object._upperThreshold = max;
}
// Create IJKtoXYZ matris
var IJKToRAS = goog.vec.Mat4.createFloat32();
goog.vec.Mat4.setRowValues(IJKToRAS,
3,
0,
0,
0,
1);
// fill in IJKToRas
goog.vec.Mat4.setRowValues(IJKToRAS, 0, -1, 0, 0, MRI.nx);
goog.vec.Mat4.setRowValues(IJKToRAS, 1, 0, 0, -1, MRI.ny);
goog.vec.Mat4.setRowValues(IJKToRAS, 2, 0, -1, 0, MRI.nz);
// IJK to RAS and invert
MRI.IJKToRAS = IJKToRAS;
MRI.RASToIJK = goog.vec.Mat4.createFloat32();
goog.vec.Mat4.invert(MRI.IJKToRAS, MRI.RASToIJK);
// get bounding box
// Transform ijk (0, 0, 0) to RAS
var tar = goog.vec.Vec4.createFloat32FromValues(0, 0, 0, 1);
var res = goog.vec.Vec4.createFloat32();
goog.vec.Mat4.multVec4(IJKToRAS, tar, res);
// Transform ijk (spacingX, spacinY, spacingZ) to RAS
var tar2 = goog.vec.Vec4.createFloat32FromValues(1, 1, 1, 1);
var res2 = goog.vec.Vec4.createFloat32();
goog.vec.Mat4.multVec4(IJKToRAS, tar2, res2);
// get location of 8 corners and update BBox
var _dims = [MRI.nx, MRI.ny, MRI.nz];
var _rasBB = X.parser.computeRASBBox(IJKToRAS, _dims);
// grab the RAS dimensions
MRI.RASSpacing = [res2[0] - res[0], res2[1] - res[1], res2[2] - res[2]];
MRI.RASDimensions = [_rasBB[1] + _rasBB[0] + 1, _rasBB[3] - _rasBB[2] + 1, _rasBB[5] - _rasBB[4] + 1];
// grab the RAS Origin
MRI.RASOrigin = [_rasBB[0], _rasBB[2], _rasBB[4]];
//grab the IJK dimensions
object._dimensions = _dims;
// create the object
object.create_(MRI);
// re-slice the data according each direction.
object._image = this.reslice(object);
X.TIMERSTOP(this._classname + '.parse');
// the object should be set up here, so let's fire a modified event
var modifiedEvent = new X.event.ModifiedEvent();
modifiedEvent._object = object;
modifiedEvent._container = container;
this.dispatchEvent(modifiedEvent);
};
/**
*Parse the data stream following the MRC file format
*File format specifications can be found at http://bio3d.colorado.edu/imod/doc/mrc_format.txt
*
* @param {!ArrayBuffer} data The data stream
* @return {Object} the MRI structure which holds all parsed information
*/
X.parserMRC.prototype.parseStream = function(data) {
this._data = data;
var MRI = {
nx: 0, //Number of Columns
ny: 0, //Number of Rows
nz: 0, //Number of Sections
mode: 0, //Type of pixel in image. Values used by IMOD
nxstart: 0, //Startin poin to sub image (not used in IMOD)
nystart: 0,
nzstart: 0,
mx: 0, //Grid size in X, Y, Z
my: 0,
mz: 0,
xlen: 0, //Cell size; pixel spacing = xlen/mx...
ylen: 0,
zlen: 0,
alpha: 0, //cell angles - ignored by IMOD
beta: 0,
gamma: 0,
mapc: 0, //map column
mapr: 0, //map row
maps: 0, //map section
amin: 0, //Minimum pixel value
amax: 0, //Maximum pixel value
amean: 0, //mean pixel value
ispg: 0, //space group numbe (ignored by IMOD0
next: 0, //number of bytes in extended header
creatid: 0, //is 0
extra: null,
nint: 0, // number of intergers or bytes per section
nreal: 0, // Number of reals per section
extra: null,
imodStamp: 0, //1146047817 = file created by IMOD
imodFlags: 0, //Bit flags
idtype: 0,
lens: 0,
nd1: 0,
nd2: 0,
vd1: 0,
vd2: 0,
tiltangles: null,
xorg: 0, //Orgin of the image
yorg: 0,
zorg: 0,
cmap: 0, //Contains "MAP "
stamp: 0, //Frist two bytes = 17 17 for bin-endian or 68 and 65 for littl-edian
rms: 0, //RMS deviation of densitites from mean density
nlabl: 0, //number of lables with useful data
data: null, //10 lables of 80 characters
min: Infinity,
max: -Infinity,
mean: 0,
space: null,
spaceorientation: null,
rasspaceorientation: null,
orientation: null,
normcosine: null
};
//Check Edianness
this.jumpTo(parseInt(212));
MRI.stamp = this.scan('schar');
if (MRI.stamp == 17) {
data = this.filpEdianness;
}
this.jumpTo(parseInt(0));
// Reading the data. Names are the names used in C code.
MRI.nx = this.scan('sint');
MRI.ny = this.scan('sint');
MRI.nz = this.scan('sint');
MRI.mode = this.scan('sint');
// size of the image
var volsize = MRI.nx * MRI.ny * MRI.nz ;
// Read for the type of pixels
this.jumpTo(parseInt(1024));
switch (MRI.mode) {
case 0:
MRI.data = this.scan('schar', volsize);
break;
case 1:
MRI.data = this.scan('sshort', volsize);
break;
case 2:
MRI.data = this.scan('float', volsize);
break;
case 3:
MRI.data = this.scan('uint', volsize);
break;
case 4:
MRI.data = this.scan('double', volsize);
break;
case 6:
MRI.data = this.scan('ushort', volsize);
break;
case 16:
MRI.data = this.scan('uchar', volsize);
break;
default:
throw new Error('Unsupported MRC data type: ' +MRI.mode);
}
this.jumpTo(parseInt(28));
MRI.mx = this.scan('sint');
MRI.my = this.scan('sint');
MRI.mz = this.scan('sint');
// pixel spacing = xlem/mx
MRI.xlen = this.scan('float');
MRI.ylen = this.scan('float');
MRI.zlen = this.scan('float');
MRI.alpha = this.scan('float');
MRI.beta = this.scan('float');
MRI.gamma = this.scan('float');
MRI.mapc = this.scan('sint');
MRI.mapr = this.scan('sint');
MRI.maps = this.scan('sint');
MRI.amin = this.scan('float');
MRI.amax = this.scan('float');
MRI.amean = this.scan('float');
MRI.ispeg = this.scan('sint');
MRI.next = this.scan('sint');
MRI.creatid = this.scan('short');
//Not sure what to do with the extra data, says 30 for size
MRI.nint = this.scan('short');
MRI.nreal = this.scan('short');
//Need to figure out extra data, 20 for size
MRI.imodStamp = this.scan('sint');
MRI.imodFLags = this.scan('sint');
MRI.idtype = this.scan('short');
MRI.lens = this.scan('short');
MRI.nd1 = this.scan('short');
MRI.nd2 = this.scan('short');
MRI.vd1 = this.scan('short');
MRI.vd2 = this.scan('short');
// loop this around (6 different ones)
MRI.tiltangles = this.scan('float',6);
this.jumpTo(parseInt(196));
MRI.xorg = this.scan('float');
MRI.yorg = this.scan('float');
MRI.zorg = this.scan('float');
this.jumpTo(parseInt(216));
MRI.rms = this.scan('float');
MRI.nlabl = this.scan('sint');
// 10 of 80 characters
MRI.lables = this.scan('schar', 10);
//Dealing with extended header
if (MRI.next != 0) {
this.jumpTo(parseInt(MRI.next+1024))
switch (MRI.mode) {
case 0:
MRI.data = this.scan('schar', volsize);
break;
case 1:
MRI.data = this.scan('sshort', volsize);
break;
case 2:
MRI.data = this.scan('float', volsize);
break;
case 3:
MRI.data = this.scan('uint', volsize);
break;
case 4:
MRI.data = this.scan('double', volsize);
break;
case 6:
MRI.data = this.scan('ushort', volsize);
break;
case 16:
MRI.data = this.scan('uchar', volsize);
break;
default:
throw new Error('Unsupported MRC data type: ' +MRI.mode);
};
}
// minimum, maximum, mean intensities
// centered on the mean for best viewing ability
if (MRI.amean - (MRI.amax - MRI.amean) < 0) {
MRI.min = MRI.amin;
MRI.max = MRI.amean + (MRI.amean - MRI.amin);
}
else {
MRI.min = MRI.amean - (MRI.amax - MRI.amean);
MRI.max = MRI.amax
}
return MRI;
};
// export symbols (required fro advanced compilatoin)
goog.exportSymbol('X.parserMRC', X.parserMRC);
goog.exportSymbol('X.parserMRC.prototype.parse', X.parserMRC.prototype.parse);
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,15 @@
test = function() {
//create a new test_renderer
test_renderer = new X.renderer3D();
test_renderer.init();
//load a .mrc file
var volume = new X.volume();
volume.file = 'data/test.mrc';
test_renderer.add(volume);
test_renderer.render();
};
Oops, something went wrong.

0 comments on commit 25ea88e

Please sign in to comment.