Skip to content

Commit

Permalink
pyest is broken with core radius offset
Browse files Browse the repository at this point in the history
  • Loading branch information
cudmore committed Jan 25, 2025
1 parent 46743bd commit 40cc704
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 99 deletions.
83 changes: 58 additions & 25 deletions src/pymapmanager/annotations/baseAnnotationsCore.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ def getMedianZ(self, segmentID : int):
return (x, y, z)

def getSummaryDf(self) -> pd.DataFrame:
"""DataFrame with per segment info (one segment per ro)
"""DataFrame with per segment info (one segment per row)
"""
return self._summaryDf

Expand All @@ -688,7 +688,7 @@ def _buildSummaryDf(self) -> pd.DataFrame:

segmentDf = self.singleTimepoint.segments[:]

_columns = ['Segment', 'Points', 'Length', 'Radius', 'Pivot Distance']
_columns = ['Segment', 'Points', 'Length', 'Radius', 'Pivot Distance', 'Color']
summaryDf = pd.DataFrame(columns=_columns)

try:
Expand All @@ -697,6 +697,7 @@ def _buildSummaryDf(self) -> pd.DataFrame:
summaryDf.index = segmentDf.index
summaryDf['Radius'] = segmentDf['radius']
summaryDf['Pivot Distance'] = segmentDf['pivotDistance']
summaryDf['Color'] = segmentDf['color']

except (AttributeError) as e:
# when no segments
Expand Down Expand Up @@ -792,13 +793,18 @@ def getNumSegments(self) -> int:
else:
return len(self._singleTimePoint.segments[:])

def setValue(self, segmentID, value):
# abb this needs to be specifically for 'radius'
def setValue(self, colName, segmentID, value):
"""
"""
from mapmanagercore.schemas.segment import Segment

# updateSegment(self, segmentId: Keys, value: Segment, replaceLog=False, skipLog=False):
_segment = Segment(radius=value)
if colName == 'radius':
_segment = Segment(radius=value)
elif colName == 'color':
_segment = Segment(color=value)

self.singleTimepoint.updateSegment(segmentId = segmentID, value=_segment)

self._buildTimepoint()
Expand All @@ -816,8 +822,8 @@ def getPivotPoint(self):
returnPointX: List of Y values of pivot points
"""
logger.info('self._summaryDf:')
print(self._summaryDf)
# logger.info('self._summaryDf:')
# print(self._summaryDf)

returnPointX = []
returnPointY = []
Expand All @@ -837,32 +843,59 @@ def getPivotPoint(self):

return returnPointX, returnPointY, returnPointZ

def getLeftRadiusPlot(self, sliceNumber, zPlusMinus):
# segmentLines = self._df
# logger.info(f"self._fullMap segments columns {self._fullMap.segments}")
import geopandas as gp
def getRadiusPlot(self, leftRight : str, sliceNumber, zPlusMinus) -> gp.GeoSeries:
"""
Parameters
==========
leftRight : str
One of ('leftRadius', 'rightRadius')
Returns
=======
df with segmentID labels columns (x, y, z, rowIndex, color)
"""

zSlice = sliceNumber
if self.getNumSegments() == 0:
return None

# all segments (we are clipping to sliceNumber)
# this has color
segmentDf = self.singleTimepoint.segments[:]

# logger.info(f"segmentDf['leftRadius'] {segmentDf['leftRadius']}")
# logger.info('segmenDf is:')
# print(segmentDf.columns)

_startSlice = zSlice - zPlusMinus
_stopSlice = zSlice + zPlusMinus
xyLeft = clipLines(segmentDf['leftRadius'], zRange = (_startSlice, _stopSlice))
xyLeft = xyLeft.get_coordinates(include_z=True)
xyLeft['rowIndex'] = list(np.arange(len(xyLeft)))

# one row per segment -> gp.GeoSeries
xyLeft = clipLines(segmentDf[leftRight], zRange = (_startSlice, _stopSlice))

# logger.info('xyLeft is')
# print(xyLeft)

xyLeft = xyLeft.get_coordinates(include_z=True) # z is empty
xyLeft['rowIndex'] = list(np.arange(len(xyLeft))) # used to determine if points in plot are contiguous

summaryDf = self.getSummaryDf() # gives us 'Color' per segment ID
xyLeft['color'] = summaryDf.loc[xyLeft.index, 'Color']

# logger.info('after xyLeft is:')
# print(xyLeft)

return xyLeft

def getRightRadiusPlot(self, sliceNumber, zPlusMinus):
zSlice = sliceNumber
if self.getNumSegments() == 0:
return None

segmentDf = self.singleTimepoint.segments[:]
_startSlice = zSlice - zPlusMinus
_stopSlice = zSlice + zPlusMinus
xyRight= clipLines(segmentDf['rightRadius'], zRange = (_startSlice, _stopSlice))
xyRight = xyRight.get_coordinates(include_z=True)
xyRight['rowIndex'] = list(np.arange(len(xyRight)))
return xyRight
# def getRightRadiusPlot(self, sliceNumber, zPlusMinus):
# zSlice = sliceNumber
# if self.getNumSegments() == 0:
# return None

# segmentDf = self.singleTimepoint.segments[:]
# _startSlice = zSlice - zPlusMinus
# _stopSlice = zSlice + zPlusMinus
# xyRight= clipLines(segmentDf['rightRadius'], zRange = (_startSlice, _stopSlice))
# xyRight = xyRight.get_coordinates(include_z=True)
# xyRight['rowIndex'] = list(np.arange(len(xyRight)))
# return xyRight
52 changes: 37 additions & 15 deletions src/pymapmanager/interface2/core/search_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,17 +171,26 @@ def data(self, index, role) -> str:
"""

# abb adding segment color
if role == Qt.BackgroundRole:
# if role == Qt.BackgroundRole:
if role == Qt.BackgroundColorRole:
row = index.row()
col = index.column()
# Get the corresponding row within the actual dataframe
# They could be different values due to deleting
rowLabel = self._data.index.tolist()[row]
# logger.warning(f'row:{row} rowLabel:{rowLabel}')
if col==0 and rowLabel == 3:
_color = QtGui.QColor('#38ff2a')
colName = self._data.columns[col]
if colName == 'Color':
# Get the corresponding row within the actual dataframe
# They could be different values due to deleting
rowLabel = self._data.index.tolist()[row]
# logger.warning(f'row:{row} rowLabel:{rowLabel} {type(rowLabel)}')
_colorHex = self._data.loc[rowLabel, 'Color']
# logger.info(f'row:{row} col:{col} colName:{colName} _colorHex:{_colorHex}')
_color = QtGui.QColor(_colorHex)
return QtGui.QBrush(_color)

else:
if(index.row() % 2 == 0):
return QtGui.QBrush(QtGui.QColor(0,0,0))
else:
return QtGui.QBrush(QtGui.QColor(40,40,40))

# print("data", self.rowCount(None))
# print("role: ", type(role))
if role == Qt.DisplayRole:
Expand Down Expand Up @@ -331,7 +340,7 @@ def __init__(self, df : pd.DataFrame = None, name : str = None):
# Selecting only Rows - https://doc.qt.io/qt-6/qabstractitemview.html#SelectionBehavior-enum
self.setSelectionBehavior(QTableView.SelectRows)

self.setAlternatingRowColors(True)
# self.setAlternatingRowColors(True)

self.setSortingEnabled(True)

Expand Down Expand Up @@ -391,8 +400,8 @@ def showColumns(self, showColList : List[str]):
index = self.df.columns.get_loc(colName)
self.showColumn(index)
except (KeyError) as e:
logger.error(f'did not find column name {colName}')
logger.error(e)
logger.error(f'did not find column name "{colName}"')
logger.error(f'available columns are: {self.df.columns}')

def updateCurrentCol(self, newColName):
"""Called whenever signal is received to update column name
Expand Down Expand Up @@ -530,10 +539,23 @@ def getSelectedRows(self):
# logger.info(f"selectedRows {selectedRows}")
return selectedRows

# def keyPressEvent(self, event : QtGui.QKeyEvent):
# super().keyPressEvent(event)
# # abb on_selectionChanged is not using its params
# # self.on_selectionChanged(None)
def _getSelectedRowLabels(self):
"""Get selected row labels (points or segment) using row index of table
"""
selectedRows = self.getSelectedRows()

rowLabelList = []
for row in selectedRows:
try:
rowLabel = self.model._data.index[row] # abb new
rowLabel = int(rowLabel)
rowLabelList.append(rowLabel)
except (KeyError) as e:
logger.error(f'myQTableView did not find row label: {row}')
logger.error('df is:')
print(self.model._data)

return rowLabelList

def on_selectionChanged(self, item):
"""Respond to user selection.
Expand Down
3 changes: 2 additions & 1 deletion src/pymapmanager/interface2/pyMapManagerApp2.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ def loadPlugins(pluginType : str, verbose = False) -> dict:
if _widgetName == 'Stack Widget':
continue

logger.info(f' adding {pluginType} moduleName:{moduleName} _widgetName:{_widgetName}')
if verbose:
logger.info(f' adding {pluginType} moduleName:{moduleName} _widgetName:{_widgetName}')
# _showInMenu = obj.showInMenu # showInMenu is a static bool
onePluginDict = {
"pluginClass": moduleName,
Expand Down
42 changes: 20 additions & 22 deletions src/pymapmanager/interface2/runInterfaceBob.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,40 @@
from pymapmanager._logger import logger

def run():
app = PyMapManagerApp(sys.argv)

# open a single timepoint map with segments and spines
# path = mapmanagercore.data.getSingleTimepointMap()

# a single timepoint tif file (import)
# path = mapmanagercore.data.getTiffChannel_1()

# .ome.zar (local)
# path = '/Users/cudmore/Sites/MapManagerCore-Data/data/single_timepoint_v3.ome.zarr'
# path = '/Users/cudmore/Sites/MapManagerCore-Data/data/single_timepoint.ome.zarr'

# .ome.zar (remote)
# path = 'https://github.com/mapmanager/MapManagerCore-Data/raw/main/data/single_timepoint.ome.zarr'

# random ome zarr file (remote)
# path = 'https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0062A/6001240.zarr'
# random ome zarr file (local)
# path = '/Users/cudmore/Dropbox/data/ome-zarr/6001240.ome.zarr'

# open a single timepoint map with segments and spines
# path = mapmanagercore.data.getSingleTimepointMap()

# a single timepoint tif file (import)
path = mapmanagercore.data.getTiffChannel_1()

# path = mapmanagercore.data.getSingleTimepointMap()

# a mmap with multiple timepoints, connects segments and spines
# path = '/Users/cudmore/Desktop/multi_timepoint_map_seg_spine_connected.mmap'
path = mapmanagercore.data.getMultiTimepointMap()

# path = '/Users/cudmore/Desktop/yyy4.mmap'
# path = '/Users/cudmore/Desktop/single_timepoint.mmap'

# path = 'https://github.com/mapmanager/MapManagerCore-Data/raw/main/data/single_timepoint.zip.mmap'

logger.info(path)
# path = mapmanagercore.data.getMultiTimepointMap()

app = PyMapManagerApp(sys.argv)
# mw will be map widget if path has multiple timepoints, otherwise mw is a stackwidget2
mw = app.loadStackWidget(path)

# run a stack plugin
# mw.runPlugin('Stack Contrast')

# works
from pprint import pprint
# logger.info('getTimeSeriesCore')
# pprint(mw.getTimeSeriesCore().getMapImages().metadata(0).experimentMetadata.getValue('Species'))
# pprint(mw.getTimeSeriesCore().getMapImages().metadata(0).experimentMetadata.asDict())

# print('segments:')
# pprint(mw.getTimeSeriesCore().getSegments()['color'])

# zoom to point (single timepoint)
# sw2.zoomToPointAnnotation(120, isAlt=True)

Expand Down
48 changes: 45 additions & 3 deletions src/pymapmanager/interface2/stackWidgets/annotationListWidget2.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,44 @@ def __init__(self,
self._buildGui(name=name)
self._setModel()

# rewire context menu
self._myTableView.contextMenuEvent = self._contextMenuEvent

def _contextMenuEvent(self, event):
self.menu = QtWidgets.QMenu(self)
colorAction = QtWidgets.QAction('Set Color', self)
colorAction.triggered.connect(lambda: self._colorPickerSlot(event))
self.menu.addAction(colorAction)

# action = _menu.exec_(self.mapToGlobal(event.pos()))
self.menu.popup(QtGui.QCursor.pos())

def _colorPickerSlot(self, event):
"""Show color dialog and set segment color.
"""
selectedRowLabels = self._myTableView._getSelectedRowLabels()
# logger.warning(f'getSelectedRows:{selectedRowLabels}')
if len(selectedRowLabels) > 0:
selectedRowLabel = selectedRowLabels[0]
_hexColor = self._myTableView.model._data.loc[selectedRowLabel, 'Color']
# logger.info(f'_hexColor:{_hexColor}')

colorDialog = QtWidgets.QColorDialog(self)
_initColor = QtGui.QColor(_hexColor)
# logger.info(f'_initColor.name():{_initColor.name()}')

# abb TODO this is not setting the color in the dialog?
colorDialog.setCurrentColor(_initColor)

# logger.info('getting color')
newColor = colorDialog.getColor() # QColor
if newColor.isValid():
logger.info(f'selected color:{newColor.name()}') # name defaults to hex
# TODO emit color change event
from pymapmanager.interface2.stackWidgets.event.segmentEvent import SetSegmentColorEvent
setSegmentColorEvent = SetSegmentColorEvent(self, selectedRowLabel, newColor.name())
self.emitEvent(setSegmentColorEvent)

def undoEvent(self, event):
# TODO: make distinction between undo spine and segment edits
# possibly make distinction between undo (add, delet, edit)
Expand Down Expand Up @@ -311,13 +349,13 @@ def on_table_selection(self, itemList : List[int], isAlt : bool = False):
def _deleteSelected(self):
"""Delete currently selected annotations.
"""
items = self._myTableView.getSelectedRows()
logger.info(f'items:{items}')
# items = self._myTableView.getSelectedRows()
# logger.info(f'items:{items}')

spineLabelList = self._getSelectedRowLabels()
logger.info(f' delete spine label list:{spineLabelList}')

if len(items) > 0:
if len(spineLabelList) > 0:
deleteSpineEvent = DeleteSpineEvent(self, spineLabelList)
self.emitEvent(deleteSpineEvent)

Expand Down Expand Up @@ -491,6 +529,10 @@ def setRadiusEvent(self, event):
# reselect current segment
self._myTableView._selectRow([segmentID])

def setSegmentColorEvent(self, event):
logger.info('')
self._setModel()

def updateSegmentRadius(self, newRadius):
""" Update segment radius stored in backend
- each segment has its own unique radius stored
Expand Down
Loading

0 comments on commit 40cc704

Please sign in to comment.