Open holgerbrandl opened 9 years ago
These ideas are excellent indeed. I plan on incorporating this consistency check very soon.
So far the orphan cells are all localized at the marging of the segmentation mask.
@mpopovichr Just to let you know that it seems to be easy to fix
db <- movieDb
# 1/ Define neighbor relationship in each frame
dbonds <- dbGetQuery(db, "select cell_id, frame, dbond_id, conj_dbond_id, left_dbond_id from directed_bonds")
cellNeighbors <- with(dbonds, data.frame(frame, cell_id, dbond_id, left_dbond_id)) %>%
dt.merge(with(dbonds, data.frame(dbond_id=conj_dbond_id, cell_id)), by=c("dbond_id")) %>%
select(frame, cell_id=cell_id.x, neighbor_cell_id=cell_id.y)
# 2/ Check symmetry
if (nrow(cellNeighbors %>% filter(neighbor_cell_id=="10000"))==nrow(cellNeighbors %>% filter(cell_id=="10000"))){
print("OK: symmetric neighbor relationship at the margin")
} else warning("The neighbor relationship isn't symmetric at the margin")
# 3/ Identify border cells: 2 rows of cells away from the margin cell 10000
borderCells <- cellNeighbors %>%
filter(cell_id!="10000") %>% # simplify due to assumed symmetry of neighbor relationship at the margin
mutate(isMarginNeighbor = ifelse(neighbor_cell_id=="10000", TRUE, FALSE)) %>%
group_by(frame, cell_id) %>%
summarise(isCellTouchingMargin=any(isMarginNeighbor)) %>%
filter(isCellTouchingMargin) %>% print_head()
# borderCells %>% dt.merge(dbGetQuery(db, "select cell_id, frame, center_x, center_y from cells")) %>%
# render_frame(15) +
# geom_point(aes(center_x, center_y), color="red")
borderCellsTwoRows <- cellNeighbors %>%
filter(cell_id!="10000") %>%
dt.merge(with(borderCells, data.frame(frame, neighbor_cell_id=cell_id)), by = c("frame", "neighbor_cell_id")) %>%
select(-neighbor_cell_id)%>% print_head()
# borderCellsTwoRows %>% dt.merge(dbGetQuery(db, "select cell_id, frame, center_x, center_y from cells")) %>%
# render_frame(15) +
# geom_point(aes(center_x, center_y), color="green")
# 4/ Check if orphan cells are in contact to the margin or to border cells (max 2 rows from the margin)
orphanMarginCheck <- divWithoutMother %>%
rename(frame=first_occ) %>%
select(frame, cell_id, appears_by) %>%
dt.merge(borderCellsTwoRows, by = c("frame", "cell_id"), all.x=T) %>% print_head()
if (all(complete.cases(orphanMarginCheck))){
print("All orphan cells are present at the margin: change label to MovedIntoMask")
} else {
warning("Some cell lineages are broken: some divided cells do not have a mother cell within the tissue:")
brokenLineages <- orphanMarginCheck[!complete.cases(orphanMarginCheck),] %>% print_head()
print("Change label to TrackingErrAppearance")
marginOrphan <- orphanMarginCheck[complete.cases(orphanMarginCheck),] %>% print_head()
print("Change label to MovedIntoMask")
}
# orphanMarginCheck %>% dt.merge(dbGetQuery(db, "select cell_id, frame, center_x, center_y from cells")) %>%
# render_frame(15) +
# geom_point(aes(center_x, center_y), color="green")
So far, YES, they are at the margin only !
@holgerbrandl What is the most elegant way to fix this ? Before or after the DB creation ? Cheers
Let's wait for Matthias' reply since a parser fix would be the best solution here. TM is doing the right thing here imho by keeping the appears_by categorization provided by the parser.
We should perform a consistency check - every cell appearing by division should be a daughter of some cell and daughters of each dividing cell should be cells in the database! Should we flag these cells also as segmentation errors?
Every cell appearing by division should be a daughter of some cell
This means that the problematic cases are tied to the first generation which seem to be incorrectly tagged as being the result of a division. Those flags seem to be directly extracted from cell_in_frame.dat, so it could be parser problem?
Daughters of each dividing cell should be cells in the database
Seems fine at least for WT_25deg_111102_ForTissueMiner