diff --git a/src/mol-io/reader/ccp4/parser.ts b/src/mol-io/reader/ccp4/parser.ts
index 629303b84d2858f57fc18d19b4550f274176c228..087b7ffc0711d5c37e63c89365ff138b341a981c 100644
--- a/src/mol-io/reader/ccp4/parser.ts
+++ b/src/mol-io/reader/ccp4/parser.ts
@@ -109,9 +109,7 @@ async function parseInternal(file: FileHandle, ctx: RuntimeContext): Promise<Res
 }
 
 export function parse(file: FileHandle) {
-    return Task.create<Result<Schema.Ccp4File>>('Parse CCP4', async ctx => {
-        return await parseInternal(file, ctx);
-    });
+    return Task.create<Result<Schema.Ccp4File>>('Parse CCP4', ctx => parseInternal(file, ctx));
 }
 
 export default parse;
\ No newline at end of file
diff --git a/src/mol-math/linear-algebra/tensor.ts b/src/mol-math/linear-algebra/tensor.ts
index f1936a505f3d215ddc8edb9e12736e3f088cf162..3dccac7e1413476a68194042620dde4affaf387e 100644
--- a/src/mol-math/linear-algebra/tensor.ts
+++ b/src/mol-math/linear-algebra/tensor.ts
@@ -212,15 +212,21 @@ export namespace Tensor {
         return ret;
     }
 
-    export function getCanonicalAxisIndicesFastToSlow(order: number[]) {
+    function reorder(xs: number[], indices: number[]) {
+        const ret: number[] = [];
+        for (let i = 0; i < xs.length; i++) ret[i] = xs[indices[i]];
+        return ret;
+    }
+
+    export function convertToCanonicalAxisIndicesFastToSlow(order: number[]) {
         const indices = new Int32Array(order.length) as any as number[];
         for (let i = 0; i < order.length; i++) indices[order[i]] = i;
-        return indices;
+        return (xs: number[]) => reorder(xs, indices);
     }
 
-    export function getCanonicalAxisIndicesSlowToFast(order: number[]) {
+    export function convertToCanonicalAxisIndicesSlowToFast(order: number[]) {
         const indices = new Int32Array(order.length) as any as number[];
         for (let i = 0; i < order.length; i++) indices[order[order.length - i - 1]] = i;
-        return indices;
+        return (xs: number[]) => reorder(xs, indices);
     }
 }
\ No newline at end of file
diff --git a/src/mol-model/volume/formats/ccp4.ts b/src/mol-model/volume/formats/ccp4.ts
index bed2de43b102abfeeb99e260d4e2c3497a16dab2..eaa685c1eebd53312011f299bded0c7081b686a4 100644
--- a/src/mol-model/volume/formats/ccp4.ts
+++ b/src/mol-model/volume/formats/ccp4.ts
@@ -32,21 +32,42 @@ function volumeFromCcp4(source: Ccp4File): Task<VolumeData> {
         const cell = SpacegroupCell.create(
             header.ISPG,
             Vec3.create(header.xLength, header.yLength, header.zLength),
-            Vec3.create(degToRad(header.alpha), degToRad(header.beta), degToRad(header.gamma)
-        ))
+            Vec3.create(degToRad(header.alpha), degToRad(header.beta), degToRad(header.gamma))
+        );
 
-        const origin = Vec3.create(header.originX, header.originY, header.originZ)
-        const dimensions = Vec3.create(header.NX, header.NY, header.NZ)
-        const axisOrder = Vec3.create(header.MAPC - 1, header.MAPR - 1, header.MAPS - 1)
+        const axis_order_fast_to_slow = Vec3.create(header.MAPC - 1, header.MAPR - 1, header.MAPS - 1);
+        const normalizeOrder = Tensor.convertToCanonicalAxisIndicesFastToSlow(axis_order_fast_to_slow);
 
-        const space = Tensor.Space(dimensions, axisOrder, header.MODE === 0 ? Int8Array : Float32Array);
+        const grid = [header.NX, header.NY, header.NZ];
+        const extent = normalizeOrder([header.NC, header.NR, header.NS]);
+
+        const gridOrigin: number[] = normalizeOrder([header.NCSTART, header.NRSTART, header.NSSTART]);
+
+        // TODO: this is code from LiteMol, but not sure about the part based on originXYZ. The 
+        // if (header.originX === 0.0 && header.originY === 0.0 && header.originZ === 0.0) {
+        //     gridOrigin = normalizeOrder([header.NCSTART, header.NRSTART, header.NSSTART]);
+        // } else {
+        //     // Use ORIGIN records rather than old n[xyz]start records
+        //     //   http://www2.mrc-lmb.cam.ac.uk/image2000.html
+        //     // XXX the ORIGIN field is only used by the EM community, and
+        //     //     has undefined meaning for non-orthogonal maps and/or
+        //     //     non-cubic voxels, etc.
+        //     gridOrigin = [header.originX, header.originY, header.originZ];
+        // }
+
+        const origin_frac = Vec3.create(gridOrigin[0] / grid[0], gridOrigin[1] / grid[1], gridOrigin[2] / grid[2]);
+        const dimensions_frac = Vec3.create(extent[0] / grid[0], extent[1] / grid[1], extent[2] / grid[2]);
+
+        const space = Tensor.Space(extent, Tensor.invertAxisOrder(axis_order_fast_to_slow), header.MODE === 0 ? Int8Array : Float32Array);
         const data = Tensor.create(space, Tensor.Data1(values));
 
         // TODO Calculate stats? When to trust header data?
+        // Min/max/mean are reliable (based on LiteMol/DensityServer usage)
+        // These, however, calculate sigma, so no data on that.
 
         return {
             cell,
-            fractionalBox: Box3D.create(origin, Vec3.add(Vec3.zero(), origin, dimensions)),
+            fractionalBox: Box3D.create(origin_frac, Vec3.add(Vec3.zero(), origin_frac, dimensions_frac)),
             data,
             dataStats: {
                 min: header.AMIN,
diff --git a/src/mol-model/volume/formats/density-server.ts b/src/mol-model/volume/formats/density-server.ts
index 10f3609bccf17d6a8ea92896524a4472c3a010bc..c01282e8e9d69ebd0cb24e35fef3730da9b0f337 100644
--- a/src/mol-model/volume/formats/density-server.ts
+++ b/src/mol-model/volume/formats/density-server.ts
@@ -10,10 +10,6 @@ import { Task } from 'mol-task';
 import { SpacegroupCell, Box3D } from 'mol-math/geometry';
 import { Tensor, Vec3 } from 'mol-math/linear-algebra';
 
-function normalizeOrder(v: number[], indices: number[]) {
-    return Vec3.create(v[indices[0]], v[indices[1]], v[indices[2]])
-}
-
 function parseDensityServerData(source: DensityServer_Data_Database): Task<VolumeData> {
     return Task.create<VolumeData>('Parse Volume Data', async ctx => {
         const { volume_data_3d_info: info, volume_data_3d: values } = source;
@@ -25,17 +21,17 @@ function parseDensityServerData(source: DensityServer_Data_Database): Task<Volum
 
         const axis_order_fast_to_slow = info.axis_order.value(0);
 
-        const indices = Tensor.getCanonicalAxisIndicesFastToSlow(axis_order_fast_to_slow);
+        const normalizeOrder = Tensor.convertToCanonicalAxisIndicesFastToSlow(axis_order_fast_to_slow);
 
         // sample count is in "axis order" and needs to be reordered
-        const sample_count = normalizeOrder(info.sample_count.value(0), indices);
+        const sample_count = normalizeOrder(info.sample_count.value(0));
         const tensorSpace = Tensor.Space(sample_count, Tensor.invertAxisOrder(axis_order_fast_to_slow), Float32Array);
 
         const data = Tensor.create(tensorSpace, Tensor.Data1(values.values.toArray({ array: Float32Array })));
 
         // origin and dimensions are in "axis order" and need to be reordered
-        const origin = normalizeOrder(info.origin.value(0), indices)
-        const dimensions = normalizeOrder(info.dimensions.value(0), indices);
+        const origin = Vec3.ofArray(normalizeOrder(info.origin.value(0)))
+        const dimensions = Vec3.ofArray(normalizeOrder(info.dimensions.value(0)));
 
         return {
             cell,