denpy is a Python package designed for manipulating the DEN file format. The main module DEN
contains functions for conversion between DEN
and numpy.array
. Other modules include functions and methods for processing computed tomographic data, DICOM files and generating Shepp-Logan phantoms.
SSH clone
git clone [email protected]:kulvait/KCT_denpy.git
To install the package, execute the following command
pip install git+https://github.com/kulvait/KCT_denpy.git
For an editable local install from the git directory, use the following command
git clone https://github.com/kulvait/KCT_denpy.git
cd KCT_denpy
pip install --user --upgrade -e .
To update the package, use
pip install --upgrade git+https://github.com/kulvait/KCT_denpy.git
For a local upgrade from the git directory:
pip install --user --upgrade .
The denpy.DEN module provides tools to manipulate DEN files in Python. The DEN format includes a short header specifying the dimensionality of the data, making it particularly convenient for computed tomography applications.
Typical import of the module
from denpy import DEN
Getting information about the DEN file
info = DEN.readHeader(file_path)
: Reads the header of a DEN file and returns a dictionary with the header information.
Important fields of the info dictionary
info["dimspec"]
: Dimensions of the data (e.g., (512, 256, 128) for a 3D dataset, which corresponds to 128 frames of xdim x ydim = 512 x 256).info["dimcount"]
: Number of dimensions in the datainfo["dimcount"] = len(info["dimspec"])
.info["shape"]
: Shape of the array that can be read withDEN.getNumpyArray
, which is flipped compared toinfo["dimspec"]
because of the way NumPy indexes arrays.
Reading and writing entire files
x = DEN.getNumpyArray(file_path)
: Reads the entire DEN file and returns it as a NumPy array.DEN.writeEmptyDEN(file_path, [dimx, dimy, dimz], force=True)
: Writes an empty DEN file with the specified dimensions.DEN.storeNdarrayAsDEN(file_path, x, force=True)
: Writes a NumPy array to a DEN file.
Note that flipped order of the Numpy array dimensions allows user to use f = x[0] to read the first frame in the file, keep in mind that first index to the Numpy array is the slowest changing index, so the last index in info["dimspec"]
.
Reading individual frames
DEN.getFrame(file_path, index)
: Reads a single frame (slice) from a DEN file and returns it as a NumPy array.DEN.writeFrame(file_path, index, frame, force=True)
: Writes a single frame (slice) to a DEN file.
The denpy.COR module is used to detect the center of rotation in tomographic data from synchrotron sources.
The denpy.DICOM module helps in reading DICOM files and is mainly intended for parsing series of data from CT perfusion acquisitions.
The denpy.PHANTOM module generates various forms of the Shepp-Logan phantom. It aims to provide a well-defined version of this phantom in both 2D and 3D, addressing inconsistencies in previous definitions.
The denpy.UTILS module provides utilities for parsing simple parameter files.
The following code demonstrates the basic usage of the denpy
package for reading a stack of 3D projection data and converting them to TIFF images.
from denpy import DEN # Import the DEN module
from PIL import Image
import numpy as np
import os
def write_slice(img, file_name, force=False):
if os.path.exists(file_name) and not force:
raise IOError(f"File {file_name} already exists!")
im = Image.fromarray(img, mode='F') # float32
im.save(file_name, "TIFF")
def convert_den_to_tiff(input_den, output_dir, force=False, suffix=""):
header = DEN.readHeader(input_den)
if header["dimcount"] < 2:
print(f"File {input_den} is {header['dimcount']}-dimensional, too few dimensions to convert to TIFF.")
return
xdim, ydim = header["dimspec"][:2]
if not os.path.exists(output_dir):
os.makedirs(output_dir)
if header["dimcount"] == 2:
write_slice(DEN.getFrame(input_den, 0), f"{output_dir}/{suffix}.tif", force)
else:
frame_count = np.prod(header["dimspec"][2:])
significant_digits = int(np.log10(frame_count)) + 1
format_string = f"{{:0{significant_digits}d}}"
for index in np.ndindex(header["dimspec"][2:]):
index_str = "_".join(format_string.format(e) for e in index)
write_slice(DEN.getFrame(input_den, index), f"{output_dir}/{index_str}{suffix}.tif", force)
# Example usage
input_den = 'path/to/input.den'
output_dir = 'path/to/output/dir'
convert_den_to_tiff(input_den, output_dir, force=True, suffix='_projection')
write_slice
function: Saves an image slice as a TIFF file, optionally overwriting existing files.convert_den_to_tiff
function:
- Reads the header of the DEN file to get dimensional information.
- Checks if the data has at least two dimensions.
- Creates the output directory if it doesn't exist.
- Writes each frame (slice) to a TIFF file, formatting the file names according to the slice index.
Replace 'path/to/input.den' and 'path/to/output/dir' with the actual paths to your DEN file and desired output directory. The force=True
argument allows overwriting existing files, and suffix='__projection' adds a suffix to the output file names. Adjust these as needed for your use case.
In the scripts
directory, you can find example scripts and useful tools for working with the denpy package. These files are not part of the main package but can be helpful references.
Unless otherwise specified in the source files, this project is licensed under the GNU General Public License v3.0.
Copyright (C) 2018-2024 Vojtěch Kulvait
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 3 of the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
If you find this software useful, you can support its development through a donation.