Author: Jesus G. Galaz-Montoya Date: October 2021 Last Update: February 2025 License: GNU General Public License v3.0 (GPL-3.0) Repository: https://github.com/jgalaz84/relative_density
This program measures total average density in 3D image files (HDF/MRC formats) using various statistical criteria. It supports optional preprocessing filters including lowpass, FSC-based filtering, and phase randomization.
The primary use case is computing density ratios between two volumes as a proxy for occupancy measurements (e.g., comparing antibody binding to glycoprotein trimers).
Citation: If you use this tool, please cite: Galaz-Montoya, J.G. (2025). Relative Density Analyzer for CryoEM/ET. https://github.com/jgalaz84/relative_density
Required:
- Python 3.7 or higher
- EMAN2 (version 2.91 or higher)
- Available at: https://blake.bcm.edu/emanwiki/EMAN2/Install
- Provides: EMData, E2init, E2end, EMArgumentParser, EMAN2_utils
Optional (for testing):
- NumPy (usually included with EMAN2)
The software has been tested on:
- macOS 10.15+ (Catalina and later)
- Linux Ubuntu 18.04+
- Linux CentOS 7+
Note: EMAN2 is required and must be properly installed. The software will work on any platform where EMAN2 is available.
- Standard desktop/laptop computer
- Minimum 4 GB RAM (8 GB recommended for large volumes)
- No GPU required
- No other non-standard hardware required
Typical installation time: < 5 minutes on a standard desktop computer (excluding EMAN2 installation)
1. Install EMAN2 (if not already installed):
# Follow instructions at: https://blake.bcm.edu/emanwiki/EMAN2/Install
# Or using conda:
conda create -n eman2 eman2 -c cryoem -c conda-forge
conda activate eman22. Download this software:
# From GitHub (once published):
git clone https://github.com/[username]/relative_density.git
cd relative_density
# Or download and extract the release archive3. Make the script executable:
chmod +x relative_density.py4. Verify installation:
# Activate EMAN2 environment
conda activate eman2 # or your EMAN2 environment name
# Check help message
./relative_density.py --help
# Run test suite
./test_relative_density.py1. Generate test data and run demo:
conda activate eman2
./test_relative_density.pyThe demo will:
- Create test volumes (4 files: .hdf and .mrc formats)
- Process them with various options
- Display results and validation
Console output excerpt:
Found 3 file(s) to process:
- vol1_high.hdf
- vol2_low.hdf
- vol3_gaussian.hdf
Processing: vol1_high.hdf
Mean (positive, non-zero) = 8.702138
Sigma (positive, non-zero) = 14.313747
============================================================
Processing complete: 3 succeeded, 0 failed
============================================================
Results saved to: test_density_analysis/results_01/hdf_results.txt
✓ All tests completed successfully!
Result files will be created in: test_density_analysis/results_*/
Result file format:
# File: vol1_high.hdf
mpnz = 8.702138
spnz = 14.313747
- Test suite: ~10-20 seconds on a standard desktop computer
- Single volume analysis: < 1 second per file (for typical 64³ to 256³ volumes)
- Large volumes (512³): 2-5 seconds per file
Minimal command (process all MRC files):
./relative_density.py --input .mrcProcess specific file:
./relative_density.py --input my_volume.hdfProcess with verbose output:
./relative_density.py --input .mrc --verbose 1This example demonstrates estimating antibody occupancy on viral glycoprotein trimers.
You must have:
- Masked volume of reference structure (e.g.,
trimer_masked.mrc) - Masked volume of query structure (e.g.,
antibody_masked.mrc) - Both volumes from the same particle-averaged reconstruction
- Masks should be tight (exclude background/solvent)
Step 1: Prepare masked volumes (done externally in Chimera/ChimeraX/EMAN2)
# Example using e2proc3d.py to apply masks:
e2proc3d.py average_map.mrc trimer_masked.mrc --mult=trimer_mask.mrc
e2proc3d.py average_map.mrc antibody_masked.mrc --mult=antibody_mask.mrcStep 2: Filter both volumes to same resolution (CRITICAL!)
./relative_density.py --input trimer_masked.mrc \
--lowpassres 15 \
--output trimer_density.txt \
--verbose 1
./relative_density.py --input antibody_masked.mrc \
--lowpassres 15 \
--output antibody_density.txt \
--verbose 1Step 3: Extract density values
# trimer_density.txt contains:
# mpnz = 45.231
# antibody_density.txt contains:
# mpnz = 27.139Step 4: Calculate occupancy fraction
Occupancy = antibody_density / trimer_density
= 27.139 / 45.231
= 0.60
= 60%
Interpretation: This indicates that approximately 60% of particles in the dataset had antibody bound, while 40% did not. In the particle-averaged structure, the trimer is always present (contributing to its full density), but the antibody is only present in 60% of particles, resulting in 60% relative density.
Alternative interpretation: All particles could have antibody bound, but with high flexibility, resulting in lower observed density. Distinguishing between partial occupancy and flexibility requires additional experiments (e.g., classification, crosslinking).
| Option | Type | Description |
|---|---|---|
--input |
string | Required. File name or pattern (e.g., .mrc, masked) |
--output |
string | Output filename (default: results.txt) |
--path |
string | Output directory (default: relativedensity) |
--lowpassres |
float | Resolution in Å for lowpass filter (CRITICAL for comparisons) |
--fscfile |
string | FSC file for Wiener filtering (exclusive with --lowpassres) |
--randomphase |
flag | Phase randomization at --lowpassres (for controls) |
--onlymean |
flag | Output only mean values |
--onlysigma |
flag | Output only sigma values |
--verbose |
int | Verbosity level 0-9 (default: 0) |
Process multiple files with pattern:
./relative_density.py --input _masked.mrc --output all_masked.txtApply phase randomization (negative control):
./relative_density.py --input map.mrc \
--lowpassres 20 \
--randomphase \
--output randomized.txtFSC-based filtering:
./relative_density.py --input halfmap1.hdf \
--fscfile fsc_curve.txt \
--output filtered.txtCustom output directory:
./relative_density.py --input .mrc \
--path analysis_results \
--output density_stats.txtStandard output file format:
# File: volume_name.mrc
mpnz = 8.702138
spnz = 14.313747
# File: another_volume.mrc
mpnz = 4.397220
spnz = 4.468962
Metric definitions:
mpnz: Mean of positive (≥0) non-zero voxels, scaled ×1000spnz: Standard deviation of positive non-zero voxels, scaled ×1000
Note: All values are scaled by 1000 for readability.
This tool measures the mean density within masked regions of particle-averaged cryoEM/ET reconstructions. By comparing densities between different structural components in the same averaged map, we can estimate the fraction of particles containing each component.
- Same particle average: Both compared volumes must come from the same particle-averaged reconstruction
- Proper masking: Masks must tightly define regions of interest, excluding background
- Matched resolution: Volumes must be filtered to the same resolution before comparison
- Normalized reconstruction: Standard cryoEM reconstruction normalization applied
Example: Trimer density = 100, Antibody density = 60
Interpretation:
The density ratio directly reflects the fraction of particles with each component.
Example: If antibody density / trimer density = 0.60, this indicates that 60% of particles in the dataset had antibody bound, while 40% did not.
- Not absolute occupancy: Provides relative measurements only
- Resolution-dependent: Must filter to matched resolution
- Masking-sensitive: Incorrect masks will bias results
- B-factor effects: Flexible regions appear low-density regardless of occupancy
- Always filter to same resolution (
--lowpassres) - Use tight, accurate masks
- Report filtering and masking procedures
Problem: "No files found matching pattern"
# Solution: Verify files exist and pattern is correct
ls *.mrc # Check files
./relative_density.py --input .mrc # Include the dot!Problem: Very different densities than expected
# Solution: Check normalization and masking
e2display.py your_volume.mrc # Visualize first
# Ensure both volumes from same reconstructionProblem: Results inconsistent between runs
# Solution: Always use same resolution filtering
./relative_density.py --input vol1.mrc --lowpassres 15
./relative_density.py --input vol2.mrc --lowpassres 15This software is released under the GNU General Public License v3.0 (GPL-3.0), an Open Source Initiative (OSI) approved license.
Key permissions:
- ✓ Commercial use
- ✓ Modification
- ✓ Distribution
- ✓ Private use
Conditions:
- License and copyright notice must be included
- Source code must be made available when distributing
- Modifications must be released under same license
Full license text: https://www.gnu.org/licenses/gpl-3.0.en.html
Bug reports and feature requests: Please open an issue on the GitHub repository: https://github.com/jgalaz84/relative_density/issues
Questions: Contact: Jesus G. Galaz-Montoya (jgalaz@gmail.com)
Contributing: Contributions are welcome! Please submit pull requests to the GitHub repository.
This tool uses the EMAN2 software package:
- Tang, G., Peng, L., Baldwin, P.R., Mann, D.S., Jiang, W., Rees, I., Ludtke, S.J. (2007). EMAN2: an extensible image processing suite for electron microscopy. J Struct Biol 157(1):38-46.
-
v1.0 (February 2025): Initial public release
- Core density measurement functionality
- HDF/MRC format support
- Lowpass, FSC, and phase randomization filtering
- Comprehensive documentation and testing
-
v0.1 (October 2021): Initial development version