def variance(session, maps): sum = sum2 = None for v in maps: from numpy import float32 m = v.full_matrix().astype(float32) if sum is None: sum = m.copy() sum2 = m * m else: if m.shape != sum.shape: from chimerax.core.errors import UserError raise UserError('Map %s' % v.name_with_id() + ' size (%d,%d,%d)' % tuple(v.data.size) + ' does not match map %s' % maps[0].name_with_id() + ' size (%d,%d,%d)' % tuple(maps[0].data.size)) sum += m sum2 += m * m n = len(maps) var = sum2 / n - (sum * sum) / (n * n) d = maps[0].data from chimerax.map_data import ArrayGridData grid = ArrayGridData(var, origin=d.origin, step=d.step, cell_angles=d.cell_angles, rotation=d.rotation, name='variance of %d maps' % n) from chimerax.map import volume_from_grid_data v = volume_from_grid_data(grid, session) return v
def ones_volume(surfaces, pad, spacing, border, default_size=100, value_type=None): # Figure out array size bounds = scene_bounds(surfaces) bsize = [s + 2 * pad + 2 * border for s in bounds.size()] if spacing is None: s = max(bsize) / default_size spacing = (s, s, s) from math import ceil size = [1 + int(ceil(s / sp)) for s, sp in zip(bsize, spacing)] origin = [x - (pad + border) for x in bounds.xyz_min] # Create ones array from numpy import ones, int8 vtype = int8 if value_type is None else value_type varray = ones(size[::-1], vtype) from chimerax.map_data import ArrayGridData g = ArrayGridData(varray, origin, spacing, name='mask') # Create Volume model from chimerax.map import volume_from_grid_data v = volume_from_grid_data(g, surfaces[0].session, open_model=False, show_dialog=False) return v
def flattened_grid(volume, method='multiply linear', step=1, subregion=None, region=None, fitregion=None, task=None): v = volume if region is None: region = v.subregion(step, subregion) m = v.region_matrix(region).copy() if fitregion: fregion = v.subregion(step, fitregion) mfit = v.region_matrix(fregion) moffset = [i - fi for i, fi in zip(region[0], fregion[0])] else: mfit = m moffset = (0, 0, 0) flatten_matrix(m, method, mfit, moffset, task=task) from chimerax.map_data import ArrayGridData d = v.data if v.name.endswith('flat'): name = v.name else: name = '%s flat' % v.name forigin, fstep = v.region_origin_and_step(region) fg = ArrayGridData(m, forigin, fstep, d.cell_angles, d.rotation, name=name) return fg
def _generate_data_array(self, origin, grid_origin, dim): data = self._data_fill_target = numpy.empty(dim, numpy.float32) order = numpy.array([2, 1, 0], int) from chimerax.map_data import ArrayGridData darray = ArrayGridData(data.transpose(), origin=origin, step=self.voxel_size, cell_angles=self.cell.angles_deg) return darray
def fourier_transform(v, step=None, subregion=None, model_id=None, phase=False): m = v.matrix(step=step, subregion=subregion) from numpy.fft import fftn cftm = fftn(m) # Complex128 result, same array size as input from numpy import absolute, angle, float32 if phase: aftm = angle(cftm).astype(float32) # Radians else: aftm = absolute(cftm).astype(float32) aftm *= 1.0 / aftm.size # Normalization aftm[0, 0, 0] = 0 # Constant term often huge making histogram hard to use cftm = None # Release memory ftm = fftshift(aftm) aftm = None # Release memory # Place FT centered on data, scaled to keep same volume xyz_min, xyz_max = v.xyz_bounds() xyz_center = map(lambda a, b: 0.5 * (a + b), xyz_min, xyz_max) ijk_size = list(ftm.shape) ijk_size.reverse() if step is None: ijk_step = v.region[2] elif isinstance(step, int): ijk_step = (step, step, step) else: ijk_step = step xyz_size = [a - b for a, b in zip(xyz_max, xyz_min)] vol = xyz_size[0] * xyz_size[1] * xyz_size[2] cell_size = [a * b for a, b in zip(v.data.step, ijk_step)] cell_vol = cell_size[0] * cell_size[1] * cell_size[2] scale = pow(vol * cell_vol, 1.0 / 3) step = [scale / a for a in xyz_size] origin = [c - 0.5 * s * z for c, s, z in zip(xyz_center, step, ijk_size)] from chimerax.map_data import ArrayGridData ftd = ArrayGridData(ftm, origin, step) ftd.name = v.name + (' FT phase' if phase else ' FT') from chimerax.map import volume_from_grid_data ftr = volume_from_grid_data(ftd, v.session, model_id=model_id) ftr.copy_settings_from(v, copy_thresholds=False, copy_colors=False, copy_region=False) ftr.set_parameters(show_outline_box=True) v.display = False # Hide original map return ftr
def tile_planes(v, axis = 'z', pstep = 1, trim = 0, rows = None, columns = None, fill_order = 'ulh', step = None, subregion = None, model_id = None): vreg = v.subregion(step = step, subregion = subregion) reg = [list(ijk) for ijk in vreg] ac,ar,a = {'x':(1,2,0), 'y':(2,0,1), 'z':(0,1,2)}[axis] reg[0][a] += trim reg[1][a] -= trim reg[2][a] = pstep dorigin, dstep = v.region_origin_and_step(reg) m = v.region_matrix(reg) tcount = m.shape[2-a] if tcount == 0: return if rows is None and columns is None: # Choose columns to make square aspect ratio. w,h = m.shape[2-ac]*dstep[ac], m.shape[2-ar]*dstep[ar] from math import sqrt, ceil columns = min(tcount, int(ceil(sqrt(tcount*float(h)/w)))) rows = (tcount - 1 + columns) // columns elif rows is None: rows = (tcount - 1 + columns) // columns elif columns is None: columns = (tcount - 1 + rows) // rows s0, s1, s2 = m.shape if axis == 'z': tshape = (1,rows*s1,columns*s2) elif axis == 'y': tshape = (columns*s0,1,rows*s2) elif axis == 'x': tshape = (rows*s0,columns*s1,1) from numpy import zeros ta = zeros(tshape, m.dtype) for i in range(tcount): # Start with top image in upper left corner. p,r,c = tile_position(i, rows, columns, tcount, fill_order) if axis == 'z': ta[0,r*s1:(r+1)*s1,c*s2:(c+1)*s2] = m[p,:,:] elif axis == 'y': ta[c*s0:(c+1)*s0,0,r*s2:(r+1)*s2] = m[:,p,:] elif axis == 'x': ta[r*s0:(r+1)*s0,c*s1:(c+1)*s1,0] = m[:,:,p] from chimerax.map_data import ArrayGridData td = ArrayGridData(ta, dorigin, dstep) td.name = v.name + ' tiled %s' % axis from chimerax.map import volume_from_grid_data tv = volume_from_grid_data(td, v.session, model_id = model_id) tv.copy_settings_from(v, copy_region = False, copy_active = False, copy_xform = open) v.display = False # Hide original map return tv
def unbend_volume(volume, path, yaxis, xsize, ysize, grid_spacing, subregion='all', step=1, model_id=None): # Compute correctly spaced cubic splined path points. points = spline_path(path, grid_spacing) axes = path_point_axes(points, yaxis) nx = int(xsize / grid_spacing) + 1 ny = int(ysize / grid_spacing) + 1 nz = len(points) # Create a rectangle of point positions to interpolate at. from numpy import empty, float32, arange section = empty((ny, nx, 3), float32) x = arange(nx, dtype=float32) * grid_spacing - 0.5 * (xsize - 1.0) y = arange(ny, dtype=float32) * grid_spacing - 0.5 * (ysize - 1.0) for j in range(ny): section[j, :, 0] = x for i in range(nx): section[:, i, 1] = y section[:, :, 2] = 0 s = section.reshape((ny * nx, 3)) # Interpolate planes to fill straightened array. from chimerax.geometry import translation m = empty((nz, ny, nx), float32) for k in range(nz): tf = translation(points[k]) * axes[k] m[k, :, :] = volume.interpolated_values(s, tf, subregion=subregion, step=step).reshape((ny, nx)) # Create volume. from chimerax.map_data import ArrayGridData step = [grid_spacing] * 3 origin = [0, 0, 0] g = ArrayGridData(m, origin, step, name='unbend') from chimerax.map import volume_from_grid_data v = volume_from_grid_data(g, volume.session, model_id=model_id) v.copy_settings_from(volume, copy_region=False, copy_active=False, copy_xform=open) return v
def lattice_models(session, seg, max_surfaces=100): # Map lattice id to dictionary mapping segment index to (descrip, color) lattice_segs = {} for segment in seg.segments: v = segment.three_d_volume if v is not None: lseg = lattice_segs.setdefault(v.lattice_id, {}) if v.value is not None: lseg[int(v.value)] = (segment.biological_annotation, segment.colour) scale, shift = guess_scale_and_shift(seg) # Create Volume model of segment indices for each lattice. models = [] lattices = seg.lattices for i, lattice in enumerate(lattices): d = lattice.data_array # Docs say number array, but emd 1547 gives bytes name = 'region map' if len(lattices) == 1 else 'region map %d' % i from chimerax.map_data import ArrayGridData g = ArrayGridData(d, step=scale, origin=shift, name=name) from chimerax.map import volume_from_grid_data v = volume_from_grid_data(g, session, open_model=False) v.display = False if lattice.id in lattice_segs: v.segments = lseg = lattice_segs[lattice.id] set_segmentation_image_colors(v, lseg) # Make a surface for each segment. regions = list(lseg.items()) regions.sort() surfs = [ segment_surface(v, sindex, descrip, color) for sindex, (descrip, color) in regions[:max_surfaces] ] if surfs: ns, nr = len(surfs), len(regions) sname = ('%d surfaces' % ns) if ns == nr else ('%d of %d surfaces' % (ns, nr)) from chimerax.core.models import Model surf_group = Model(sname, v.session) surf_group.add(surfs) models.append(surf_group) # TODO: Don't see how to get the transform id for the lattice. # EMD 1547 segmentation has two transforms, identity and the # map transform (2.8A voxel size, shift to center) but I didn't # find any place where transform 1 is associated with the lattice. # Appears it should be in segment.three_d_volume.transform_id but this # attribute is optional and is None in this case. models.append(v) return models
def ridge_grid(volume, level=None, step=1, subregion=None): v = volume region = v.subregion(step, subregion) m = v.region_matrix(region) rm = ridge_matrix(m, level) from chimerax.map_data import ArrayGridData d = v.data name = '%s ridges' % v.name origin, step = v.region_origin_and_step(region) rg = ArrayGridData(rm, origin, step, d.cell_angles, d.rotation, name=name) return rg
def bounding_grid(xyz, step, pad, transforms=None): from chimerax.geometry import bounds b = bounds.point_bounds(xyz, transforms) origin = [x - pad for x in b.xyz_min] from math import ceil shape = [ int(ceil((b.xyz_max[a] - b.xyz_min[a] + 2 * pad) / step)) for a in (2, 1, 0) ] from numpy import zeros, float32 matrix = zeros(shape, float32) from chimerax.map_data import ArrayGridData grid = ArrayGridData(matrix, origin, (step, step, step)) return grid
def falloff_grid(volume, iterations = 10, step = 1, subregion = None): v = volume region = v.subregion(step, subregion) from numpy import float32 m = v.region_matrix(region).astype(float32) falloff_matrix(m, iterations) from chimerax.map_data import ArrayGridData d = v.data name = '%s falloff' % v.name forigin, fstep = v.region_origin_and_step(region) fg = ArrayGridData(m, forigin, fstep, d.cell_angles, d.rotation, name = name) return fg
def map_covering_box(v, ijk_min, ijk_max, ijk_cell_size, symmetries, step): d = v.data if ijk_cell_size == d.size and (symmetries is None or len(symmetries) == 0): # Full unit cell and no symmetries to average. g = v.grid_data(subregion='all', step=step, mask_zone=False) from chimerax.map import volume cg = volume.map_from_periodic_map(g, ijk_min, ijk_max) return cg out_ijk_size = tuple(a - b + 1 for a, b in zip(ijk_max, ijk_min)) from chimerax.geometry import translation out_ijk_to_vijk_transform = translation(ijk_min) ijk_symmetries = ijk_symmetry_matrices(d, symmetries) from numpy import empty, float32 shape = list(reversed(out_ijk_size)) m = empty(shape, float32) from chimerax.map import extend_crystal_map nnc, dmax = extend_crystal_map(v.full_matrix(), ijk_cell_size, ijk_symmetries.array(), m, out_ijk_to_vijk_transform.matrix) log = v.session.logger log.info( 'Extended map %s to box of size (%d, %d, %d),\n' % ((v.name, ) + out_ijk_size) + ' cell size (%d, %d, %d) grid points, %d symmetry operations,\n' % (tuple(ijk_cell_size) + (len(ijk_symmetries), )) + ' %d points not covered by any symmetry,\n' % nnc + ' maximum value difference where symmetric map copies overlap = %.5g\n' % dmax) if nnc > 0: log.status('%d grid points not covered' % nnc) origin = d.ijk_to_xyz(ijk_min) from chimerax.map_data import ArrayGridData g = ArrayGridData(m, origin, d.step, d.cell_angles, name=v.name + ' extended') return g
def sphere_volume(session, n, r, noise=1.0): from numpy import indices, single as floatc o = 0.5 * (n - 1) i = indices((n, n, n), floatc) - o a = (i[0, ...] * i[0, ...] + i[1, ...] * i[1, ...] + i[2, ...] * i[2, ...] < r * r).astype(floatc) if noise > 0: from numpy.random import normal a += normal(0, noise, a.shape) from chimerax.map_data import ArrayGridData g = ArrayGridData(a, origin=(-o, -o, -o), step=(1, 1, 1), name='sphere') from chimerax.map import volume_from_grid_data v = volume_from_grid_data(g, session) return v
def _generate_data_array(self, coords, step, radius, pad=0): import numpy if hasattr(step, '__len__'): step = min(step) step = max((step, radius / 4)) step = min(step, 1.5) step = numpy.ones(3) * step cmin = coords.min(axis=0) cmax = coords.max(axis=0) mincoor = cmin - radius - pad maxcoor = cmax + radius + pad dim = numpy.ceil((maxcoor - mincoor) / step).astype(numpy.int) data = numpy.zeros(dim, numpy.uint8) self._data_fill_target = data from chimerax.map_data import ArrayGridData darray = ArrayGridData(data.transpose(), origin=mincoor, step=step) return darray
def unroll_operation(v, r0, r1, h, center, axis, gsp, subregion, step, modelId): from math import ceil, pi zsize = int(max(1, ceil(h / gsp))) # cylinder height xsize = int(max(1, ceil((r1 - r0) / gsp))) # slab thickness rmid = 0.5 * (r0 + r1) circum = rmid * 2 * pi ysize = int(max(1, ceil(circum / gsp))) # circumference from chimerax.geometry import normalize_vector axis = normalize_vector(axis) agrid_points = annulus_grid(r0, r1, center, axis, ysize, xsize) grid_points = agrid_points.reshape((ysize * xsize, 3)) grid_points[:] += tuple([-0.5 * h * ai for ai in axis]) # Shift annulus. from numpy import empty values = empty((zsize, ysize, xsize), v.data.value_type) axis_step = tuple([h * float(ai) / (zsize - 1) for ai in axis]) for i in range(zsize): vval = v.interpolated_values(grid_points, subregion=subregion, step=step) values[i, :, :] = vval.reshape((ysize, xsize)) grid_points[:] += axis_step # Shift annulus. from chimerax.map_data import ArrayGridData gstep = (float(r1 - r0) / (xsize - 1), circum / (ysize - 1), float(h) / (zsize - 1)) gorigin = (center[0] + r0, center[1] - 0.5 * circum, center[2] - 0.5 * h) g = ArrayGridData(values, gorigin, gstep, name='unrolled %s' % v.name) from chimerax.map import volume_from_grid_data vu = volume_from_grid_data(g, v.session, model_id=modelId) vu.copy_settings_from(v, copy_region=False, copy_active=False, copy_colors=False) if axis[0] != 0 or axis[1] != 0: # Rotate so unrolled volume is tangential to cylinder from chimerax.geometry import orthonormal_frame vu.position = v.position * orthonormal_frame(axis) return vu
def array_to_model(mvol, volume, ijk_origin, model_id): # Create masked volume grid object. from chimerax.map_data import ArrayGridData g = volume.data morigin = g.ijk_to_xyz_transform * ijk_origin m = ArrayGridData(mvol, morigin, g.step, cell_angles=g.cell_angles, rotation=g.rotation, name=g.name + ' masked') # Create masked volume object. from chimerax.map import volume_from_grid_data v = volume_from_grid_data(m, volume.session, model_id=model_id) v.copy_settings_from(volume, copy_region=False) v.show() return v
def mlp_map(session, atoms, method, spacing, max_dist, nexp, name, open_map): data, bounds = calculatefimap(atoms, method, spacing, max_dist, nexp) # m.pot is 1-dimensional if m.writedxfile() was called. Has indices in x,y,z order. origin = tuple(xmin for xmin, xmax in bounds) s = spacing step = (s, s, s) from chimerax.map_data import ArrayGridData g = ArrayGridData(data, origin, step, name=name) g.polar_values = True from chimerax.map import volume_from_grid_data v = volume_from_grid_data(g, session, open_model=open_map, show_dialog=open_map) if open_map: v.update_drawings() # Compute surface levels v.set_parameters( surface_colors=[(0, 139 / 255, 139 / 255, 1), (184 / 255, 134 / 255, 11 / 255, 1)]) return v
def laplacian(v, step=None, subregion=None, model_id=None): m = v.matrix(step=step, subregion=subregion) from numpy import float32, multiply, add lm = m.astype(float32) # Copy array multiply(lm, -6.0, lm) add(lm[:-1, :, :], m[1:, :, :], lm[:-1, :, :]) add(lm[1:, :, :], m[:-1, :, :], lm[1:, :, :]) add(lm[:, :-1, :], m[:, 1:, :], lm[:, :-1, :]) add(lm[:, 1:, :], m[:, :-1, :], lm[:, 1:, :]) add(lm[:, :, :-1], m[:, :, 1:], lm[:, :, :-1]) add(lm[:, :, 1:], m[:, :, :-1], lm[:, :, 1:]) lm[0, :, :] = 0 lm[-1, :, :] = 0 lm[:, 0, :] = 0 lm[:, -1, :] = 0 lm[:, :, 0] = 0 lm[:, :, -1] = 0 origin, step = v.data_origin_and_step(subregion=subregion, step=step) d = v.data from chimerax.map_data import ArrayGridData ld = ArrayGridData(lm, origin, step, d.cell_angles, d.rotation, name=v.name + ' Laplacian') ld.polar_values = True from chimerax.map import volume_from_grid_data lv = volume_from_grid_data(ld, v.session, model_id=model_id) lv.copy_settings_from(v, copy_thresholds=False, copy_colors=False) lv.set_parameters(cap_faces=False) v.display = False # Hide original map return lv
def threshold_grid(volume, minimum=None, set_minimum=None, maximum=None, set_maximum=None, step=1, subregion=None, region=None): v = volume if region is None: region = v.subregion(step, subregion) origin, step = v.region_origin_and_step(region) m = v.region_matrix(region).copy() import numpy from numpy import array, putmask if not minimum is None: t = array(minimum, m.dtype) if set_minimum is None or set_minimum == minimum: numpy.maximum(m, t, m) else: putmask(m, m < t, array(set_minimum, m.dtype)) if not maximum is None: t = array(maximum, m.dtype) if set_maximum is None or set_maximum == maximum: numpy.minimum(m, t, m) else: putmask(m, m > t, array(set_maximum, m.dtype)) from chimerax.map_data import ArrayGridData d = v.data if v.name.endswith('thresholded'): name = v.name else: name = '%s thresholded' % v.name tg = ArrayGridData(m, origin, step, d.cell_angles, d.rotation, name=name) return tg
def local_correlation(map1, map2, window_size, subtract_mean, model_id=None): d1 = map1.data m1 = map1.full_matrix() d2 = map2.data m2, same = map2.interpolate_on_grid(map1) mc = local_correlation_matrix(m1, m2, window_size, subtract_mean) hs = 0.5 * (window_size - 1) origin = tuple(o + hs * s for o, s in zip(d1.origin, d1.step)) from chimerax.map_data import ArrayGridData g = ArrayGridData(mc, origin, d1.step, d1.cell_angles, d2.rotation, name='local correlation') from chimerax.map import volume_from_grid_data mapc = volume_from_grid_data(g, map1.session, model_id=model_id) mapc.position = map1.position return mapc
def gaussian_grid(volume, sdev, step = 1, subregion = None, region = None, value_type = None, invert = False, task = None): v = volume if region is None: region = v.subregion(step, subregion) origin, step = v.region_origin_and_step(region) sdev3 = (sdev,sdev,sdev) if isinstance(sdev,(float,int)) else sdev ijk_sdev = [float(sd)/s for sd,s in zip(sdev3,step)] m = v.region_matrix(region) gm = gaussian_convolution(m, ijk_sdev, value_type = value_type, invert = invert, task = task) from chimerax.map_data import ArrayGridData d = v.data if v.name.endswith('gaussian'): name = v.name else: name = '%s gaussian' % v.name gg = ArrayGridData(gm, origin, step, d.cell_angles, d.rotation, name = name) return gg
def median_grid(volume, bin_size=3, iterations=1, step=1, subregion=None, region=None): v = volume if region is None: region = v.subregion(step, subregion) origin, step = v.region_origin_and_step(region) vm = v.region_matrix(region) m = vm for i in range(iterations): m = median_array(m, bin_size) from chimerax.map_data import ArrayGridData d = v.data if v.name.endswith('median'): name = v.name else: name = '%s median' % v.name mg = ArrayGridData(m, origin, step, d.cell_angles, d.rotation, name=name) return mg
def processed_volume(v, subregion = None, step = None, value_type = None, threshold = None, zero_mean = False, scale_factor = None, match_scale = None, enclose_volume = None, fast_enclose_volume = None, normalize_level = None, align_to = None, on_grid = None, mask = None, final_value_type = None): d = v.data region = None if not subregion is None or not step is None: from chimerax.map.volume import full_region ijk_min, ijk_max = full_region(d.size)[:2] if subregion is None else subregion ijk_step = (1,1,1) if step is None else step region = (ijk_min, ijk_max, ijk_step) from chimerax.map_data import GridSubregion d = GridSubregion(d, ijk_min, ijk_max, ijk_step) if (value_type is None and threshold is None and not zero_mean and scale_factor is None and match_scale is None and align_to is None and mask is None and final_value_type is None): return d m = d.full_matrix() if not value_type is None: m = m.astype(value_type) if not threshold is None: from numpy import array, putmask t = array(threshold, m.dtype) putmask(m, m < t, 0) if zero_mean: from numpy import float64 mean = m.mean(dtype = float64) m = (m - mean).astype(m.dtype) if not scale_factor is None: m = (m*scale_factor).astype(m.dtype) if not match_scale is None: ms = match_scale.region_matrix(region) if region else match_scale.full_matrix() from numpy import float64, einsum m1, ms1 = m.sum(dtype = float64), ms.sum(dtype = float64) m2, ms2, mms = einsum('ijk,ijk',m,m,dtype=float64), einsum('ijk,ijk',ms,ms,dtype=float64), einsum('ijk,ijk',m,ms,dtype=float64) n = m.size a = (mms - m1*ms1/n) / (m2 - m1*m1/n) b = (ms1 - a*m1) / n am = a*m am += b print ('scaling #%s' % v.id_string, a, b, m1, ms1, m2, ms2, mms, am.mean(), am.std(), ms.mean(), ms.std()) m[:] = am.astype(m.dtype) if not enclose_volume is None or not fast_enclose_volume is None: set_enclosed_volume(v, enclose_volume, fast_enclose_volume) if not normalize_level is None: level = v.maximum_surface_level if level is None: from chimerax.core.errors import UserError raise UserError('vseries save: normalize_level used but no level set for volume %s' % v.name) if zero_mean: level -= mean scale = normalize_level / level m = (m*scale).astype(m.dtype) if not align_to is None: align(v, align_to) if not on_grid is None: vc = v.writable_copy(value_type = m.dtype, unshow_original = False) vc.full_matrix()[:,:,:] = m m = on_grid.full_matrix() m[:,:,:] = 0 on_grid.add_interpolated_values(vc) vc.close() d = on_grid.data if not mask is None: m[:,:,:] *= mask.full_matrix() if not final_value_type is None: m = m.astype(final_value_type) from chimerax.map_data import ArrayGridData d = ArrayGridData(m, d.origin, d.step, d.cell_angles, d.rotation) return d
def matching_grid(grid): from numpy import zeros, float32 matrix = zeros(grid.full_matrix().shape, float32) from chimerax.map_data import ArrayGridData g = ArrayGridData(matrix, grid.origin, grid.step) return g
def grid_data_from_state(s, gdcache, session, file_paths): if 'array' in s: from numpy import frombuffer, dtype from gzip import decompress from base64 import b64decode a = frombuffer(decompress(b64decode(s['array'])), dtype = dtype(s['value_type'])) if not a.flags.writeable: a = a.copy() array = a.reshape(s['size'][::-1]) from chimerax.map_data import ArrayGridData dlist = [ArrayGridData(array)] else: dbfetch = s.get('database_fetch') ask = (dbfetch is None) if s.get('series_index',0) >= 1 or s.get('time',0) >= 1: ask = False path = absolute_path(s['path'], file_paths, ask = ask, base_path = session.session_file_path) empty_path = (path is None or path == '' or path == () or path == []) if empty_path and dbfetch is None: return None else: gid = s.get('grid_id','') file_type = s['file_type'] dlist = open_data(path, gid, file_type, dbfetch, gdcache, session) for data in dlist: data.name = s['name'] if 'xyz_step' in s: for data in dlist: data.set_step(s['xyz_step']) if 'xyz_origin' in s: for data in dlist: data.set_origin(s['xyz_origin']) if 'cell_angles' in s: for data in dlist: data.set_cell_angles(s['cell_angles']) if 'rotation' in s: for data in dlist: data.set_rotation(s['rotation']) if 'symmetries' in s: for data in dlist: data.symmetries = s['symmetries'] if 'series_index' in s: for data in dlist: data.series_index = s['series_index'] if 'channel' in s: for data in dlist: data.channel = s['channel'] if 'time' in s: for data in dlist: data.time = s['time'] if 'available_subsamplings' in s: # Subsamples may be from separate files or the same file. from chimerax.map_data import SubsampledGrid dslist = [] for data in dlist: if not isinstance(data, SubsampledGrid): data = SubsampledGrid(data) dslist.append(data) dlist = dslist for cell_size, dstate in s['available_subsamplings'].items(): dpath = absolute_path(dstate.path, file_paths, base_path = session.session_file_path) if dpath != path: # TODO: This looks wrong. Don't we just recurse calling grid_data_from_state()? ssdlist = dstate.create_object(gdcache) for i,ssdata in enumerate(ssdlist): dlist[i].add_subsamples(ssdata, cell_size) return dlist