Skip to content

Commit ecf2a2c

Browse files
committed
Split off reading of ROI table
Currently does exactly the same as before, but should help us introduce more flexibility, particularly to customise for different versions of the LabView setup.
1 parent 444c9b1 commit ecf2a2c

2 files changed

Lines changed: 67 additions & 23 deletions

File tree

src/silverlabnwb/nwb_file.py

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from . import metadata
2020
from .header import LabViewHeader, LabViewVersions
2121
from .imaging import Modes
22+
from .rois import RoiReader
2223
from .timings import LabViewTimings231, LabViewTimingsPre2018
2324

2425
try:
@@ -969,28 +970,11 @@ def add_rois(self, roi_path):
969970
organised by ROI number and channel name, so we can iterate there. Issue #16.
970971
"""
971972
self.log('Loading ROI locations from {}', roi_path)
972-
assert os.path.isfile(roi_path)
973-
roi_data = pd.read_csv(
974-
roi_path, sep='\t', header=0, index_col=False, dtype=np.float16,
975-
converters={'Z start': np.float64, 'Z stop': np.float64}, memory_map=True)
976-
# Rename the columns so that we can use them as identifiers later on
977-
column_mapping = {
978-
'ROI index': 'roi_index', 'Pixels in ROI': 'num_pixels',
979-
'X start': 'x_start', 'Y start': 'y_start', 'Z start': 'z_start',
980-
'X stop': 'x_stop', 'Y stop': 'y_stop', 'Z stop': 'z_stop',
981-
'Laser Power (%)': 'laser_power', 'ROI Time (ns)': 'roi_time_ns',
982-
'Angle (deg)': 'angle_deg', 'Composite ID': 'composite_id',
983-
'Number of lines': 'num_lines', 'Frame Size': 'frame_size',
984-
'Zoom': 'zoom', 'ROI group ID': 'roi_group_id'
985-
}
986-
roi_data.rename(columns=column_mapping, inplace=True)
973+
reader = RoiReader()
974+
roi_data = reader.read_roi_table(roi_path)
987975
module = self.nwb_file.create_processing_module(
988976
'Acquired_ROIs',
989977
'ROI locations and acquired fluorescence readings made directly by the AOL microscope.')
990-
# Convert some columns to int
991-
roi_data = roi_data.astype(
992-
{'x_start': np.uint16, 'x_stop': np.uint16, 'y_start': np.uint16, 'y_stop': np.uint16,
993-
'num_pixels': int})
994978
seg_iface = ImageSegmentation()
995979
module.add(seg_iface)
996980
self._write()
@@ -1015,9 +999,8 @@ def add_rois(self, roi_path):
1015999
)
10161000
# Specify the non-standard data we will be storing for each ROI,
10171001
# which includes all the raw data fields from the original file
1018-
plane.add_column('dimensions', 'Dimensions of the ROI')
1019-
for old_name, new_name in column_mapping.items():
1020-
plane.add_column(new_name, old_name)
1002+
for column_name, column_description in reader.columns.items():
1003+
plane.add_column(column_name, column_description)
10211004
index = 0 # index of the row as it will be stored in the ROI table
10221005
self.roi_mapping[plane_name] = {}
10231006
for row in roi_group.itertuples():
@@ -1044,7 +1027,7 @@ def add_rois(self, roi_path):
10441027
pixels[i, 2] = 1 # weight for this pixel
10451028
plane.add_roi(id=roi_id, pixel_mask=[tuple(r) for r in pixels.tolist()],
10461029
dimensions=dimensions,
1047-
**{field: getattr(row, field) for field in column_mapping.values()})
1030+
**reader.get_row_attributes(row))
10481031
self.roi_mapping[plane_name][roi_id] = index
10491032
index += 1
10501033
self._write()

src/silverlabnwb/rois.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"""Functionality for handling Regions of Interest in different versions."""
2+
3+
import os
4+
5+
import numpy as np
6+
import pandas as pd
7+
8+
9+
class RoiReader:
10+
"""A class for reading ROI information."""
11+
def __init__(self):
12+
self.column_mapping = {
13+
'ROI index': 'roi_index', 'Pixels in ROI': 'num_pixels',
14+
'X start': 'x_start', 'Y start': 'y_start', 'Z start': 'z_start',
15+
'X stop': 'x_stop', 'Y stop': 'y_stop', 'Z stop': 'z_stop',
16+
'Laser Power (%)': 'laser_power', 'ROI Time (ns)': 'roi_time_ns',
17+
'Angle (deg)': 'angle_deg', 'Composite ID': 'composite_id',
18+
'Number of lines': 'num_lines', 'Frame Size': 'frame_size',
19+
'Zoom': 'zoom', 'ROI group ID': 'roi_group_id'
20+
}
21+
22+
@property
23+
def columns(self):
24+
column_descriptions = {
25+
'dimensions': 'Dimensions of the ROI'
26+
}
27+
# for old_name, new_name in self.column_mapping.items():
28+
# column_descriptions[new_name] = old_name
29+
column_descriptions.update({
30+
new_name: old_name
31+
for old_name, new_name in self.column_mapping.items()
32+
})
33+
return column_descriptions
34+
35+
def read_roi_table(self, roi_path):
36+
assert os.path.isfile(roi_path)
37+
roi_data = pd.read_csv(
38+
roi_path, sep='\t', header=0, index_col=False, dtype=np.float16,
39+
converters={'Z start': np.float64, 'Z stop': np.float64}, memory_map=True)
40+
# Rename the columns so that we can use them as identifiers later on
41+
column_mapping = {
42+
'ROI index': 'roi_index', 'Pixels in ROI': 'num_pixels',
43+
'X start': 'x_start', 'Y start': 'y_start', 'Z start': 'z_start',
44+
'X stop': 'x_stop', 'Y stop': 'y_stop', 'Z stop': 'z_stop',
45+
'Laser Power (%)': 'laser_power', 'ROI Time (ns)': 'roi_time_ns',
46+
'Angle (deg)': 'angle_deg', 'Composite ID': 'composite_id',
47+
'Number of lines': 'num_lines', 'Frame Size': 'frame_size',
48+
'Zoom': 'zoom', 'ROI group ID': 'roi_group_id'
49+
}
50+
roi_data.rename(columns=column_mapping, inplace=True)
51+
# Convert some columns to int
52+
roi_data = roi_data.astype(
53+
{'x_start': np.uint16, 'x_stop': np.uint16, 'y_start': np.uint16, 'y_stop': np.uint16,
54+
'num_pixels': int})
55+
return roi_data
56+
57+
def get_row_attributes(self, roi_row):
58+
return {
59+
field: getattr(roi_row, field)
60+
for field in self.column_mapping.values()
61+
}

0 commit comments

Comments
 (0)