Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
cc40039
Update fileformats.py
alphataubio May 4, 2025
f8a48bc
Create __init__.py
alphataubio May 4, 2025
ce58c75
Create grid.py
alphataubio May 4, 2025
7bf9987
Create test_grid.py
alphataubio May 4, 2025
01cc1a6
still getting "Multiple formats support .grid3d" *^&*%*^%((*&)&*^%^%@…
alphataubio May 5, 2025
51465c5
Merge branch 'RBVI:develop' into alphataubio-grid
alphataubio May 6, 2025
e2d46fc
rename grid to lammps/grid3d
alphataubio May 6, 2025
299de17
Merge branch 'alphataubio-grid' of https://github.com/alphataubio/Chi…
alphataubio May 6, 2025
3d58db4
3rd try
alphataubio May 6, 2025
8ccab15
Update fileformats.py
alphataubio May 6, 2025
0e16c8e
Update manager.py
alphataubio May 6, 2025
a1bf19a
Update bundle_info.xml
alphataubio May 6, 2025
590c802
Update lammps_format.py
alphataubio May 6, 2025
e1122c4
cleanup
alphataubio May 6, 2025
0a52b45
Update lammps_format.py
alphataubio May 6, 2025
245fe62
handle almost all possible lammps custom dump formats
alphataubio May 6, 2025
99159d6
Merge branch 'RBVI:develop' into alphataubio-grid
alphataubio May 7, 2025
dd72944
Merge branch 'alphataubio-grid' of https://github.com/alphataubio/Chi…
alphataubio May 7, 2025
fdddb1b
fix error: package directory 'src/dcd/MDToolsMarch97/data' does not e…
alphataubio May 8, 2025
06f4ad6
Update manager.py
alphataubio May 8, 2025
410b0cb
Update lammps_format.py
alphataubio May 8, 2025
ac00bc3
Update bundle_info.xml
alphataubio May 8, 2025
da3d881
Update read_lammps.py
alphataubio May 8, 2025
a410e93
Update bundle_info.xml
alphataubio May 8, 2025
2d5864f
Merge branch 'RBVI:develop' into alphataubio-grid
alphataubio May 16, 2025
d04d721
add lammps grid3d test
alphataubio May 16, 2025
8259311
Update fileformats.py
alphataubio May 16, 2025
ff8baad
Merge branch 'alphataubio-grid' of https://github.com/alphataubio/Chi…
alphataubio May 16, 2025
39a3519
Update bundle_info.xml
alphataubio May 16, 2025
d9f942c
Update bundle_info.xml
alphataubio May 16, 2025
9f620a5
Update fileformats.py
alphataubio May 16, 2025
728c780
Create nitrite.grid3d
alphataubio May 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/bundles/map/bundle_info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<Provider name="IMAGIC density map" want_path="true" batch="true" />
<Provider name="Imaris map" want_path="true" batch="true" />
<Provider name="IMOD map" want_path="true" batch="true" />
<Provider name="LAMMPS grid3d" want_path="false" batch="true" />
<Provider name="MacMolPlt grid" want_path="true" batch="true" />
<Provider name="MRC density map" want_path="true" batch="true" />
<Provider name="NetCDF map" want_path="true" batch="true" />
Expand Down
1 change: 1 addition & 0 deletions src/bundles/map_data/bundle_info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
suffixes=".hed,.img" />
<Provider name="Imaris map" nicknames="ims" category="Volume data" suffixes=".ims" />
<Provider name="IMOD map" nicknames="imodmap" category="Volume data" suffixes=".rec" />
<Provider name="LAMMPS grid3d" nicknames="grid3d" category="Volume data" suffixes=".grid3d" />
<Provider name="MacMolPlt grid" nicknames="macmolplt" category="Volume data" suffixes=".mmp" />
<Provider name="MRC density map" nicknames="mrc" category="Volume data" suffixes=".mrc" />
<Provider name="NetCDF map" nicknames="netcdfmap" category="Volume data"
Expand Down
2 changes: 1 addition & 1 deletion src/bundles/map_data/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ TOP = ../../../..
include $(TOP)/mk/config.make

SUBDIRS = amira apbs brix ccp4 cmap delphi deltavision dock dsn6 emanhdf gaussian \
gopenmol hdf imagestack imagic imod ims macmolplt mrc priism profec \
gopenmol hdf imagestack imagic imod ims lammps macmolplt mrc priism profec \
pif situs spider tom_em uhbd xplor

PKG_DIR = $(PYSITEDIR)/chimerax/map_data
Expand Down
5 changes: 3 additions & 2 deletions src/bundles/map_data/src/fileformats.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ def save_func(self):
MapFileFormat('SPIDER volume data', 'spider', ['spider'], ['spi','vol']),
MapFileFormat('TOM toolbox EM density map', 'tom_em', ['tom_em'], ['em']),
MapFileFormat('UHBD grid, binary', 'uhbd', ['uhbd'], ['grd']),
]
MapFileFormat('LAMMPS grid3d', 'lammps', ['lammps'], ['grid3d']),
]

# -----------------------------------------------------------------------------
# The electrostatics file types are opened using a surface colormapping tool
Expand Down Expand Up @@ -181,7 +182,7 @@ def open_file(path, file_type = None, **kw):
# -----------------------------------------------------------------------------
#
def file_type_from_suffix(path):

for ff in file_formats:
for suffix in ff.suffixes:
if has_suffix(path, suffix):
Expand Down
26 changes: 26 additions & 0 deletions src/bundles/map_data/src/lammps/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# === UCSF ChimeraX Copyright ===
# Copyright 2016 Regents of the University of California.
# All rights reserved. This software provided pursuant to a
# license agreement containing restrictions on its disclosure,
# duplication and use. For details see:
# https://www.rbvi.ucsf.edu/chimerax/docs/licensing.html
# This notice must be embedded in or attached to all copies,
# including partial copies, of the software or any revisions
# or derivations thereof.
# === UCSF ChimeraX Copyright ===

TOP = ../../../../..
include $(TOP)/mk/config.make

PKG_DIR = $(PYSITEDIR)/chimerax/map_data/lammps

PYSRCS = __init__.py lammps_grid.py lammps_format.py

all: $(PYOBJS)

install: all
-mkdir -p $(PKG_DIR)
$(RSYNC) $(PYSRCS) $(PKG_DIR)

clean:
rm -rf __pycache__
18 changes: 18 additions & 0 deletions src/bundles/map_data/src/lammps/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# === UCSF ChimeraX Copyright ===
# Copyright 2016 Regents of the University of California.
# All rights reserved. This software provided pursuant to a
# license agreement containing restrictions on its disclosure,
# duplication and use. For details see:
# https://www.rbvi.ucsf.edu/chimerax/docs/licensing.html
# This notice must be embedded in or attached to all copies,
# including partial copies, of the software or any revisions
# or derivations thereof.
# === UCSF ChimeraX Copyright ===

# -----------------------------------------------------------------------------
# LAMMPS grid3d dump file reader.
#

def open(path):
from .lammps_grid import LammpsGrid
return [LammpsGrid(path)]
227 changes: 227 additions & 0 deletions src/bundles/map_data/src/lammps/lammps_format.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
# === UCSF ChimeraX Copyright ===
# Copyright 2016 Regents of the University of California.
# All rights reserved. This software provided pursuant to a
# license agreement containing restrictions on its disclosure,
# duplication and use. For details see:
# https://www.rbvi.ucsf.edu/chimerax/docs/licensing.html
# This notice must be embedded in or attached to all copies,
# including partial copies, of the software or any revisions
# or derivations thereof.
# === UCSF ChimeraX Copyright ===

# -----------------------------------------------------------------------------
# Read LAMMPS grid3d format map data.
#
import os
import numpy

class Lammps_Grid_Data:
"""
Parses LAMMPS grid3d format files produced by the 'dump grid' command.
"""
def __init__(self, path):
self.path = path
self.name = os.path.basename(path)

# Parse file to get grid metadata
if path.endswith('.gz'):
import gzip
f = gzip.open(path, 'rt')
else:
f = open(path, 'r')

try:
self.parse_grid3d(f)
finally:
f.close()

def parse_grid3d(self, file):
"""Parse the LAMMPS grid3d file and extract metadata."""
# LAMMPS grid data variables
self.timesteps = []
self.matrix_size = None # (nx, ny, nz)
self.origin = None # (x0, y0, z0)
self.step = None # (dx, dy, dz)
self.columns = None # List of data column names
self.data_sections = [] # List of (timestep, start_pos, num_entries)
self.box_bounds = None # [(xmin, xmax), (ymin, ymax), (zmin, zmax)]
self.dimension = 3 # Default to 3D

# Read through file to find all sections
lines = file.readlines()
line_index = 0

while line_index < len(lines):
line = lines[line_index].strip()

# Parse ITEM: TIMESTEP
if line.startswith("ITEM: TIMESTEP"):
line_index += 1
timestep = int(lines[line_index].strip())
self.timesteps.append(timestep)

# Parse ITEM: BOX BOUNDS
elif line.startswith("ITEM: BOX BOUNDS"):
self.box_bounds = []
for dim in range(3): # Assume 3D box
line_index += 1
if line_index < len(lines):
parts = lines[line_index].strip().split()
if len(parts) >= 2:
self.box_bounds.append((float(parts[0]), float(parts[1])))

# Calculate origin from box bounds
if len(self.box_bounds) == 3:
self.origin = (self.box_bounds[0][0], self.box_bounds[1][0], self.box_bounds[2][0])

# Parse ITEM: DIMENSION
elif line.startswith("ITEM: DIMENSION"):
line_index += 1
if line_index < len(lines):
self.dimension = int(lines[line_index].strip())

# Parse ITEM: GRID SIZE (with nx ny nz tokens)
elif line.startswith("ITEM: GRID SIZE"):
line_index += 1
parts = lines[line_index].strip().split()
if len(parts) >= 3:
# LAMMPS grid dimensions are (nx, ny, nz)
self.matrix_size = (int(parts[0]), int(parts[1]), int(parts[2]))

# If we have box_bounds and matrix_size but no step, calculate it
if self.box_bounds and self.matrix_size and not self.step:
nx, ny, nz = self.matrix_size
dx = (self.box_bounds[0][1] - self.box_bounds[0][0]) / nx if nx > 1 else 1.0
dy = (self.box_bounds[1][1] - self.box_bounds[1][0]) / ny if ny > 1 else 1.0
dz = (self.box_bounds[2][1] - self.box_bounds[2][0]) / nz if nz > 1 else 1.0
self.step = (dx, dy, dz)

# Parse ITEM: GRID CELLS
elif line.startswith("ITEM: GRID CELLS"):
parts = line.split()
# Skip "ITEM: GRID CELLS" and get column names
self.columns = parts[3:] if len(parts) > 3 else ["data"]

if self.matrix_size is None:
raise ValueError("Grid size not defined before GRID CELLS section")

# Record the position in the file for later data reading
start_pos = line_index + 1

# Calculate expected number of data entries
nx, ny, nz = self.matrix_size
num_entries = nx * ny * nz

# Record data section info
current_timestep = self.timesteps[-1] if self.timesteps else 0
self.data_sections.append((current_timestep, start_pos, num_entries))

# Skip the data section - we'll read it on demand
line_index += num_entries
continue

line_index += 1

# Use first column for the initial grid
if self.columns and len(self.columns) > 0:
self.current_column = self.columns[0]
else:
raise ValueError("No grid data columns found")

# Set element type
from numpy import float32
self.element_type = float32

# Validate that we have all required metadata
if self.matrix_size is None:
raise ValueError("Grid size not found in file")
if self.origin is None:
raise ValueError("Grid origin not found in file")
if self.step is None:
raise ValueError("Grid spacing not found in file")
if not self.data_sections:
raise ValueError("No grid data sections found in file")

def read_matrix(self, ijk_origin, ijk_size, ijk_step, progress):
"""
Read and return the specified submatrix from the file.
For LAMMPS grid3d format, we need to read and parse the entire grid.
"""
# Currently just read the first data section and first column
timestep, start_pos, num_entries = self.data_sections[0]

# Read the whole file again
if self.path.endswith('.gz'):
import gzip
f = gzip.open(self.path, 'rt')
else:
f = open(self.path, 'r')

try:
lines = f.readlines()

# Create numpy array for the data
nx, ny, nz = self.matrix_size
data = numpy.zeros((nz, ny, nx), dtype=self.element_type)

# Read the data section
grid_index = 0
for i in range(num_entries):
if progress and i % 1000 == 0:
progress.percent = 100.0 * i / num_entries

line_idx = start_pos + i
if line_idx >= len(lines):
break

line = lines[line_idx].strip()
if not line: # Skip empty lines
continue

# Parse value - each line just contains a single value
try:
value = float(line)
except ValueError:
continue

# Calculate grid coordinates from linear index
# Assuming data is ordered with x changing fastest, then y, then z
# As specified in the LAMMPS documentation
ix = grid_index % nx
iy = (grid_index // nx) % ny
iz = grid_index // (nx * ny)

# Store in data array (in ZYX index order)
if 0 <= ix < nx and 0 <= iy < ny and 0 <= iz < nz:
data[iz, iy, ix] = value

grid_index += 1

# Extract the requested submatrix
submatrix = self._submatrix(data, ijk_origin, ijk_size, ijk_step)
return submatrix

finally:
f.close()

def _submatrix(self, data, ijk_origin, ijk_size, ijk_step):
"""Extract a submatrix from the data array."""
ox, oy, oz = ijk_origin
sx, sy, sz = ijk_size
stx, sty, stz = ijk_step

# Adjust for our ZYX index order
i0, i1, i2 = oz, oy, ox
s0, s1, s2 = sz, sy, sx
st0, st1, st2 = stz, sty, stx

# Extract the submatrix
if st0 == 1 and st1 == 1 and st2 == 1:
submatrix = data[i0:i0+s0, i1:i1+s1, i2:i2+s2].copy()
else:
submatrix = data[
i0:i0+s0*st0:st0,
i1:i1+s1*st1:st1,
i2:i2+s2*st2:st2].copy()

return submatrix
49 changes: 49 additions & 0 deletions src/bundles/map_data/src/lammps/lammps_grid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# === UCSF ChimeraX Copyright ===
# Copyright 2016 Regents of the University of California.
# All rights reserved. This software provided pursuant to a
# license agreement containing restrictions on its disclosure,
# duplication and use. For details see:
# https://www.rbvi.ucsf.edu/chimerax/docs/licensing.html
# This notice must be embedded in or attached to all copies,
# including partial copies, of the software or any revisions
# or derivations thereof.
# === UCSF ChimeraX Copyright ===

# === UCSF ChimeraX Copyright ===
# Copyright 2016 Regents of the University of California.
# All rights reserved. This software provided pursuant to a
# license agreement containing restrictions on its disclosure,
# duplication and use. For details see:
# https://www.rbvi.ucsf.edu/chimerax/docs/licensing.html
# This notice must be embedded in or attached to all copies,
# including partial copies, of the software or any revisions
# or derivations thereof.
# === UCSF ChimeraX Copyright ===

# -----------------------------------------------------------------------------
# Wrap LAMMPS grid3d data as grid data for displaying as surfaces, meshes, and volumes.
#
from .. import GridData

# -----------------------------------------------------------------------------
#
class LammpsGrid(GridData):
"""
Reads LAMMPS grid3d format files produced by the 'dump grid' command in LAMMPS.
"""
def __init__(self, path):

from . import lammps_format
d = lammps_format.Lammps_Grid_Data(path)

self.lammps_data = d

GridData.__init__(self, d.matrix_size, d.element_type,
origin=d.origin, step=d.step,
path=path, file_type='grid3d',
name=d.name)

# ---------------------------------------------------------------------------
#
def read_matrix(self, ijk_origin, ijk_size, ijk_step, progress):
return self.lammps_data.read_matrix(ijk_origin, ijk_size, ijk_step, progress)
Loading