convert
dreem.utils.convert
¶
Conversion utilities for importing tracking data from external formats to .slp files.
Functions:
| Name | Description |
|---|---|
convert_trackmate |
Convert TrackMate outputs to .slp files. |
make_labels |
Convert a TrackMate trajectories file and video to a SLEAP Labels object. |
nd2mp4 |
Convert an ND2 video to MP4 format. |
tif2mp4 |
Convert a TIF video to MP4 format. |
tif2npy |
Convert a TIF video to a NumPy array. |
convert_trackmate(label_files, vid_files, out_dir='.', to_npy=False, to_mp4=False)
¶
Convert TrackMate outputs to .slp files.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label_files
|
list[str]
|
Paths to TrackMate CSV/XLSX label files. |
required |
vid_files
|
list[str]
|
Paths to video files (TIF, ND2, etc.). |
required |
out_dir
|
str
|
Output directory for converted files. |
'.'
|
to_npy
|
bool
|
Convert TIF videos to .npy format. |
False
|
to_mp4
|
bool
|
Convert videos to .mp4 format. |
False
|
Source code in dreem/utils/convert.py
def convert_trackmate(
label_files: list[str],
vid_files: list[str],
out_dir: str = ".",
to_npy: bool = False,
to_mp4: bool = False,
) -> None:
"""Convert TrackMate outputs to .slp files.
Args:
label_files: Paths to TrackMate CSV/XLSX label files.
vid_files: Paths to video files (TIF, ND2, etc.).
out_dir: Output directory for converted files.
to_npy: Convert TIF videos to .npy format.
to_mp4: Convert videos to .mp4 format.
"""
out_path = Path(out_dir)
out_path.mkdir(parents=True, exist_ok=True)
if vid_files:
for vid in vid_files:
suffix = Path(vid).suffix
if ".tif" in suffix:
if to_npy:
print(f"Converting {Path(vid).stem} to .npy")
tif2npy(vid, out_dir=out_dir)
elif to_mp4:
print(f"Converting {Path(vid).stem} to .mp4")
tif2mp4(vid, out_dir=out_dir)
elif ".nd2" in suffix:
if to_mp4:
print(f"Converting {Path(vid).stem} to .mp4")
nd2mp4(vid, out_dir=out_dir)
elif to_npy:
print(
"`--to-npy` flag is currently not compatible with .nd2. "
"Use `--to-mp4` instead!"
)
continue
else:
print(f"Unknown file type, {suffix}, skipping!")
continue
if label_files and vid_files and len(label_files) > 0 and len(vid_files) > 0:
for csv_file, tif in tqdm(zip(label_files, vid_files)):
print(f"Converting {Path(csv_file).stem}\t{Path(tif).stem} to .slp")
labels = make_labels(tif, csv_file)
print(f"Saving to {out_dir}/{Path(tif).stem}.slp")
sio.save_slp(labels, f"{out_dir}/{Path(tif).stem}.slp")
else:
raise ValueError("Either labels files or video files are missing!")
make_labels(video_path, trajectories_path)
¶
Convert a TrackMate trajectories file and video to a SLEAP Labels object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
video_path
|
str
|
Path to the video file (will look for .mp4 version). |
required |
trajectories_path
|
str
|
Path to the TrackMate CSV or XLSX trajectories file. |
required |
Returns:
| Type | Description |
|---|---|
Labels
|
A SLEAP Labels object containing the converted tracking data. |
Source code in dreem/utils/convert.py
def make_labels(video_path: str, trajectories_path: str) -> sio.Labels:
"""Convert a TrackMate trajectories file and video to a SLEAP Labels object.
Args:
video_path: Path to the video file (will look for .mp4 version).
trajectories_path: Path to the TrackMate CSV or XLSX trajectories file.
Returns:
A SLEAP Labels object containing the converted tracking data.
"""
vid = sio.Video.from_filename(str(Path(video_path).with_suffix(".mp4")))
if "csv" in trajectories_path:
traj = pd.read_csv(trajectories_path, encoding="ISO-8859-1")
elif "xlsx" in trajectories_path:
traj = pd.read_excel(trajectories_path)
else:
raise ValueError(
f"Must be either csv or xlsx file. Got {Path(trajectories_path).suffix}!"
)
traj = traj.apply(pd.to_numeric, errors="coerce", downcast="integer")
traj = traj.drop(range(0, 3), axis=0)
posx_key = "POSITION_X"
posy_key = "POSITION_Y"
frame_key = "FRAME"
track_key = "TRACK_ID"
mapper = {
"X": posx_key,
"Y": posy_key,
"x": posx_key,
"y": posy_key,
"Slice n°": frame_key,
"Track n°": track_key,
}
if "t" in traj:
mapper.update({"t": frame_key})
traj = traj.rename(mapper=mapper, axis=1)
traj["TRACK_ID"] = traj["TRACK_ID"].fillna(-1)
if traj["FRAME"].min() == 1:
traj["FRAME"] = traj["FRAME"] - 1
skel = sio.Skeleton(nodes=["centroid"])
tracks = {}
lfs = []
for frame_idx in sorted(traj["FRAME"].unique()):
insts = []
lf = traj[traj["FRAME"] == frame_idx]
for inst_idx in sorted(lf["TRACK_ID"].unique()):
if inst_idx not in tracks:
if inst_idx != -1:
tracks[int(inst_idx)] = sio.Track(f"Track {int(inst_idx) + 1}")
else:
tracks[int(inst_idx)] = sio.Track("Unassigned Track")
track = tracks[int(inst_idx)]
instance = lf[lf["TRACK_ID"] == inst_idx]
pt = np.array(
(instance["POSITION_X"].iloc[0], instance["POSITION_Y"].iloc[0])
)
if np.isnan(pt).all():
print("Nan found")
try:
insts.append(
sio.Instance.from_numpy(
pt.reshape(1, 2), skeleton=skel, track=track
)
)
except Exception as e:
print(inst_idx)
raise e
lfs.append(sio.LabeledFrame(video=vid, frame_idx=frame_idx, instances=insts))
labels = sio.Labels(lfs)
labels.videos[0].backend.filename = str(Path(video_path).with_suffix(".mp4"))
return labels
nd2mp4(video_path, out_dir='.', fps=30)
¶
Convert an ND2 video to MP4 format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
video_path
|
str
|
Path to the ND2 file. |
required |
out_dir
|
str
|
Output directory for the MP4 file. |
'.'
|
fps
|
int
|
Frames per second for the output video. |
30
|
Returns:
| Type | Description |
|---|---|
bool
|
True on success. |
Source code in dreem/utils/convert.py
def nd2mp4(video_path: str, out_dir: str = ".", fps: int = 30) -> bool:
"""Convert an ND2 video to MP4 format.
Args:
video_path: Path to the ND2 file.
out_dir: Output directory for the MP4 file.
fps: Frames per second for the output video.
Returns:
True on success.
"""
from nd2reader import ND2Reader
with (
ND2Reader(video_path) as nd2,
imageio.get_writer(
f"{out_dir}/{Path(video_path).stem}.mp4", fps=fps, macro_block_size=1
) as mp4,
):
for frame in tqdm(nd2):
mp4.append_data(frame)
return True
tif2mp4(video_path, out_dir='.', fps=30)
¶
Convert a TIF video to MP4 format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
video_path
|
str
|
Path to the TIF file. |
required |
out_dir
|
str
|
Output directory for the MP4 file. |
'.'
|
fps
|
int
|
Frames per second for the output video. |
30
|
Returns:
| Type | Description |
|---|---|
bool
|
True on success. |
Source code in dreem/utils/convert.py
def tif2mp4(video_path: str, out_dir: str = ".", fps: int = 30) -> bool:
"""Convert a TIF video to MP4 format.
Args:
video_path: Path to the TIF file.
out_dir: Output directory for the MP4 file.
fps: Frames per second for the output video.
Returns:
True on success.
"""
frames = imread(video_path)
# Normalize to uint8 if needed (e.g., 16-bit microscopy images)
if frames.dtype != np.uint8:
fmin = frames.min()
fmax = frames.max()
if fmax > fmin:
frames = ((frames - fmin) / (fmax - fmin) * 255).astype(np.uint8)
else:
frames = np.zeros_like(frames, dtype=np.uint8)
with imageio.get_writer(
f"{out_dir}/{Path(video_path).stem}.mp4", fps=fps, macro_block_size=1
) as writer:
for frame in tqdm(frames):
writer.append_data(frame)
return True
tif2npy(video_path, save=True, out_dir='.')
¶
Convert a TIF video to a NumPy array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
video_path
|
str
|
Path to the TIF file. |
required |
save
|
bool
|
Whether to save the array to disk. |
True
|
out_dir
|
str
|
Output directory for the .npy file. |
'.'
|
Returns:
| Type | Description |
|---|---|
ndarray
|
The video as a NumPy array. |
Source code in dreem/utils/convert.py
def tif2npy(video_path: str, save: bool = True, out_dir: str = ".") -> np.ndarray:
"""Convert a TIF video to a NumPy array.
Args:
video_path: Path to the TIF file.
save: Whether to save the array to disk.
out_dir: Output directory for the .npy file.
Returns:
The video as a NumPy array.
"""
vid = imread(video_path)
vid = np.expand_dims(vid, -1)
if save:
print(f"Saving to {out_dir}/{Path(video_path).stem}.npy")
np.save(f"{out_dir}/{Path(video_path).stem}.npy", vid)
return vid