/* $RCSfile$
* $Author: hansonr $
* $Date: 2007-03-30 11:40:16 -0500 (Fri, 30 Mar 2007) $
* $Revision: 7273 $
*
* Copyright (C) 2007 Miguel, Bob, Jmol Development
*
* Contact: hansonr@stolaf.edu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jmol.jvxl.readers;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import org.jmol.util.BinaryDocument;
import org.jmol.util.Logger;
class MrcBinaryReader extends MapFileReader {
/*
* also referred to as CCP4 format
*
* examples include the emd_1xxx..map electron microscopy files
* and xxxx.ccp4 files
*
*
*/
MrcBinaryReader(SurfaceGenerator sg, String fileName, String data) {
super(sg, null);
binarydoc = new BinaryDocument();
if (data == null)
binarydoc.setStream(sg.getAtomDataServer().getBufferedInputStream(fileName), true);
else
binarydoc.setStream(new DataInputStream(new ByteArrayInputStream(data.getBytes())));
// data are HIGH on the inside and LOW on the outside
nSurfaces = 1;
if (params.thePlane == null)
params.insideOut = !params.insideOut;
allowSigma = true;
}
/* see http://ami.scripps.edu/software/mrctools/mrc_specification.php
*
* many thanks to Eric Martz for providing the test files that
* made this understandable.
*
1 NX number of columns (fastest changing in map)
2 NY number of rows
3 NZ number of sections (slowest changing in map)
4 MODE data type :
0 image : signed 8-bit bytes range -128 to 127
1 image : 16-bit halfwords
2 image : 32-bit reals
3 transform : complex 16-bit integers
4 transform : complex 32-bit reals
6 image : unsigned 16-bit range 0 to 65535
5 NXSTART number of first column in map (Default = 0)
6 NYSTART number of first row in map
7 NZSTART number of first section in map
8 MX number of intervals along X
9 MY number of intervals along Y
10 MZ number of intervals along Z
11-13 CELLA cell dimensions in angstroms
14-16 CELLB cell angles in degrees
17 MAPC axis corresp to cols (1,2,3 for X,Y,Z)
18 MAPR axis corresp to rows (1,2,3 for X,Y,Z)
19 MAPS axis corresp to sections (1,2,3 for X,Y,Z)
20 DMIN minimum density value
21 DMAX maximum density value
22 DMEAN mean density value
23 ISPG space group number 0 or 1 (default=0)
24 NSYMBT number of bytes used for symmetry data (0 or 80)
25-49 EXTRA extra space used for anything - 0 by default
50-52 ORIGIN origin in X,Y,Z used for transforms
53 MAP character string 'MAP ' to identify file type
54 MACHST machine stamp
55 RMS rms deviation of map from mean density
56 NLABL number of labels being used
57-256 LABEL(20,10) 10 80-character text labels
*/
protected String[] labels;
protected void readParameters() throws Exception {
int ispg;
int nsymbt;
byte[] extra = new byte[100];
byte[] map = new byte[4];
byte[] machst = new byte[4];
float rmsDeviation;
int nlabel;
nx = binarydoc.readInt(); // CCP4 "extent[0-2]"
ny = binarydoc.readInt();
nz = binarydoc.readInt();
mode = binarydoc.readInt();
if (mode < 0 || mode > 6) {
binarydoc.setIsBigEndian(false);
nx = BinaryDocument.swapBytes(nx);
ny = BinaryDocument.swapBytes(ny);
nz = BinaryDocument.swapBytes(nz);
mode = BinaryDocument.swapBytes(mode);
}
Logger.info("MRC header: mode: " + mode);
nxyzStart[0] = binarydoc.readInt(); // CCP4 "nxyzstart[0-2]"
nxyzStart[1] = binarydoc.readInt();
nxyzStart[2] = binarydoc.readInt();
na = binarydoc.readInt(); // CCP4 "grid[0-2]"
nb = binarydoc.readInt();
nc = binarydoc.readInt();
if (na == 0)
na = nx - 1;
if (nb == 0)
nb = ny - 1;
if (nc == 0)
nc = nz - 1;
a = binarydoc.readFloat();
b = binarydoc.readFloat();
c = binarydoc.readFloat();
alpha = binarydoc.readFloat();
beta = binarydoc.readFloat();
gamma = binarydoc.readFloat();
mapc = binarydoc.readInt(); // CCP4 "crs2xyz[0-2]
mapr = binarydoc.readInt();
maps = binarydoc.readInt();
if (mapc != 1 && params.thePlane == null)
params.dataXYReversed = true;
dmin = binarydoc.readFloat();
dmax = binarydoc.readFloat();
dmean = binarydoc.readFloat();
Logger.info("MRC header: dmin,dmax,dmean: " + dmin + "," + dmax + ","
+ dmean);
ispg = binarydoc.readInt();
nsymbt = binarydoc.readInt();
Logger.info("MRC header: ispg,nsymbt: " + ispg + "," + nsymbt);
binarydoc.readByteArray(extra);
origin.x = binarydoc.readFloat(); // CCP4 "origin2k"
origin.y = binarydoc.readFloat();
origin.z = binarydoc.readFloat();
binarydoc.readByteArray(map);
binarydoc.readByteArray(machst);
rmsDeviation = binarydoc.readFloat();
Logger.info("MRC header: rms: " + rmsDeviation);
nlabel = binarydoc.readInt();
Logger.info("MRC header: labels: " + nlabel);
labels = new String[nlabel];
labels[0] = "Jmol MrcBinaryReader";
for (int i = 0; i < 10; i++) {
String s = binarydoc.readString(80).trim();
if (i < nlabel) {
labels[i] = s;
Logger.info(labels[i]);
}
}
for (int i = 0; i < nsymbt; i++) {
long position = binarydoc.getPosition();
String s = binarydoc.readString(80).trim();
if (s.indexOf('\0') != s.lastIndexOf('\0')) {
// must not really be symmetry info!
Logger.error("File indicates " + nsymbt + " symmetry lines, but " + i + " found!");
binarydoc.seek(position);
break;
}
Logger.info("MRC file symmetry information: " + s);
}
Logger.info("MRC header: bytes read: " + binarydoc.getPosition()
+ "\n");
// setting the cutoff to mean + 2 x RMS seems to work
// reasonably well as a default.
getVectorsAndOrigin();
if (params.thePlane == null && (params.cutoffAutomatic || !Float.isNaN(params.sigma))) {
float sigma = (Float.isNaN(params.sigma) ? 1 : params.sigma);
params.cutoff = rmsDeviation * sigma + dmean;
Logger.info("Cutoff set to (mean + rmsDeviation*" + sigma + ")\n");
}
jvxlFileHeaderBuffer = new StringBuffer();
jvxlFileHeaderBuffer.append("MRC DATA ").append(labels[0]).append("\n");
jvxlFileHeaderBuffer.append("see http://ami.scripps.edu/software/mrctools/mrc_specification.php\n");
}
protected float nextVoxel() throws Exception {
float voxelValue;
/*
* 4 MODE data type :
0 image : signed 8-bit bytes range -128 to 127
1 image : 16-bit halfwords
2 image : 32-bit reals
3 transform : complex 16-bit integers
4 transform : complex 32-bit reals
6 image : unsigned 16-bit range 0 to 65535
*/
switch(mode) {
case 0:
voxelValue = binarydoc.readByte();
break;
case 1:
voxelValue = binarydoc.readShort();
break;
default:
case 2:
voxelValue = binarydoc.readFloat();
break;
case 3:
//read first component only
voxelValue = binarydoc.readShort();
binarydoc.readShort();
break;
case 4:
//read first component only
voxelValue = binarydoc.readFloat();
binarydoc.readFloat();
break;
case 6:
voxelValue = binarydoc.readUnsignedShort();
break;
}
nBytes = binarydoc.getPosition();
return voxelValue;
}
private static byte[] b8 = new byte[8];
protected void skipData(int nPoints) throws Exception {
for (int i = 0; i < nPoints; i++)
switch(mode) {
case 0:
binarydoc.readByte();
break;
case 1:
case 6:
binarydoc.readByteArray(b8, 0, 2);
break;
default:
case 2:
case 3:
binarydoc.readByteArray(b8, 0, 4);
break;
case 4:
binarydoc.readByteArray(b8);
break;
}
}
}