Skip to content

Commit

Permalink
feat: new utility to convert segm.npz to a dataframe of objects coord…
Browse files Browse the repository at this point in the history
…inates
  • Loading branch information
ElpadoCan committed Jun 13, 2023
1 parent d3620d5 commit 35e6f0b
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 0 deletions.
28 changes: 28 additions & 0 deletions cellacdc/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def eventFilter(self, object, event):
from cellacdc.utils import compute as utilsCompute
from cellacdc.utils import repeat as utilsRepeat
from cellacdc.utils import toImageJroi as utilsToImageJroi
from cellacdc.utils import toObjCoords as utilsToObjCoords
from cellacdc.utils import acdcToSymDiv as utilsSymDiv
from cellacdc.utils import trackSubCellObjects as utilsTrackSubCell
from cellacdc.utils import createConnected3Dsegm as utilsConnected3Dsegm
Expand Down Expand Up @@ -464,6 +465,7 @@ def createMenuBar(self):
convertMenu.addAction(self.TiffToNpzAction)
convertMenu.addAction(self.h5ToNpzAction)
convertMenu.addAction(self.toImageJroiAction)
convertMenu.addAction(self.toObjsCoordsAction)

segmMenu = utilsMenu.addMenu('Segmentation')
segmMenu.addAction(self.createConnected3Dsegm)
Expand Down Expand Up @@ -584,6 +586,9 @@ def createActions(self):
self.toImageJroiAction = QAction(
'Convert _segm.npz file(s) to ImageJ ROIs...'
)
self.toObjsCoordsAction = QAction(
'Convert _segm.npz file(s) to object coordinates (CSV)...'
)
self.createConnected3Dsegm = QAction(
'Create connected 3D segmentation mask from z-slices segmentation...'
)
Expand Down Expand Up @@ -634,6 +639,9 @@ def connectActions(self):
self.TiffToNpzAction.triggered.connect(self.launchConvertFormatUtil)
self.h5ToNpzAction.triggered.connect(self.launchConvertFormatUtil)
self.toImageJroiAction.triggered.connect(self.launchToImageJroiUtil)
self.toObjsCoordsAction.triggered.connect(
self.launchToObjectsCoordsUtil
)
self.createConnected3Dsegm.triggered.connect(
self.launchConnected3DsegmActionUtil
)
Expand Down Expand Up @@ -922,6 +930,26 @@ def _launchArboretum(self):
)
self.arboretumWindow.show()

def launchToObjectsCoordsUtil(self):
self.logger.info(f'Launching utility "{self.sender().text()}"')

selectedExpPaths = self.getSelectedExpPaths(
'From _segm.npz to objects coordinates (CSV)'
)
if selectedExpPaths is None:
return

title = 'Convert _segm.npz file(s) to objects coordinates (CSV)'
infoText = 'Launching to to objects coordinates process...'
progressDialogueTitle = (
'Converting _segm.npz file(s) to to objects coordinates (CSV)'
)
self.toObjCoordsWin = utilsToObjCoords.toObjCoordsUtil(
selectedExpPaths, self.app, title, infoText, progressDialogueTitle,
parent=self
)
self.toObjCoordsWin.show()

def launchToImageJroiUtil(self):
self.logger.info(f'Launching utility "{self.sender().text()}"')
myutils.check_install_package('roifile', parent=self)
Expand Down
18 changes: 18 additions & 0 deletions cellacdc/myutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,24 @@ def imagej_tiffwriter(
with TiffWriter(new_path, bigtiff=True) as new_tif:
new_tif.save(data)

def from_lab_to_obj_coords(lab):
rp = skimage.measure.regionprops(lab)
dfs = []
keys = []
for obj in rp:
keys.append(obj.label)
obj_coords = obj.coords
ndim = obj_coords.shape[1]
if ndim == 3:
columns = ['z', 'y', 'x']
else:
columns = ['y', 'x']
df_obj = pd.DataFrame(data=obj_coords, columns=columns)
dfs.append(df_obj)
df = pd.concat(dfs, keys = keys, names=['Cell_ID', 'idx']).droplevel(1)
return df


def from_lab_to_imagej_rois(lab, ImagejRoi, t=0, SizeT=1, max_ID=None):
if max_ID is None:
max_ID = lab.max()
Expand Down
29 changes: 29 additions & 0 deletions cellacdc/utils/toObjCoords.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from .. import myutils, workers, widgets, html_utils

from .base import NewThreadMultipleExpBaseUtil

class toObjCoordsUtil(NewThreadMultipleExpBaseUtil):
def __init__(
self, expPaths, app, title: str, infoText: str,
progressDialogueTitle: str, parent=None):
module = myutils.get_module_name(__file__)
super().__init__(
expPaths, app, title, module, infoText, progressDialogueTitle,
parent=parent
)
self.expPaths = expPaths

def runWorker(self):
self.worker = workers.ToObjCoordsWorker(self)
super().runWorker(self.worker)

def showEvent(self, event):
self.runWorker()

def workerFinished(self, worker):
super().workerFinished(worker)
txt = 'Converting to object coordinates completed.'
self.logger.info(txt)
msg = widgets.myMessageBox(wrapText=False, showCentered=False)
msg.information(self, 'Process completed', html_utils.paragraph(txt))
self.close()
69 changes: 69 additions & 0 deletions cellacdc/workers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3018,3 +3018,72 @@ def saveAlignedData(
np.savez_compressed(filePath, data)
elif ext == '.h5':
load.save_to_h5(filePath, data)

class ToObjCoordsWorker(BaseWorkerUtil):
def __init__(self, mainWin):
super().__init__(mainWin)

@worker_exception_handler
def run(self):
debugging = False
expPaths = self.mainWin.expPaths
tot_exp = len(expPaths)
self.signals.initProgressBar.emit(0)
for i, (exp_path, pos_foldernames) in enumerate(expPaths.items()):
self.errors = {}
tot_pos = len(pos_foldernames)

abort = self.emitSelectSegmFiles(exp_path, pos_foldernames)
if abort:
self.signals.finished.emit(self)
return

for p, pos in enumerate(pos_foldernames):
if self.abort:
self.signals.finished.emit(self)
return

self.logger.log(
f'Processing experiment n. {i+1}/{tot_exp}, '
f'{pos} ({p+1}/{tot_pos})'
)

images_path = os.path.join(exp_path, pos, 'Images')
endFilenameSegm = self.mainWin.endFilenameSegm
ls = myutils.listdir(images_path)
file_path = [
os.path.join(images_path, f) for f in ls
if f.endswith(f'{endFilenameSegm}.npz')
][0]

posData = load.loadData(file_path, '')

self.signals.sigUpdatePbarDesc.emit(f'Processing {posData.pos_path}')

posData.getBasenameAndChNames()
posData.buildPaths()

posData.loadOtherFiles(
load_segm_data=True,
load_metadata=True,
end_filename_segm=endFilenameSegm
)

if posData.SizeT > 1:
posData.segm_data = posData.segm_data[np.newaxis]

dfs = []
for frame_i, lab in enumerate(posData.segm_data):
df_coords_i = myutils.from_lab_to_obj_coords(
posData.segm_data
)
dfs.append(df_coords_i)

df_filepath = posData.segm_npz_path.replace('.npz', '.csv')
df_filepath = df_filepath.replace('_segm', '_objects_coordinates')

keys = list(range(len(posData.segm_data)))
df = pd.concat(dfs, keys=keys, names=['frame_i'])
df.to_csv(df_filepath)

self.signals.finished.emit(self)

0 comments on commit 35e6f0b

Please sign in to comment.