Skip to content

Commit

Permalink
Merge pull request #9 from nanthony21/dev
Browse files Browse the repository at this point in the history
0.1.11 RC
  • Loading branch information
nanthony21 authored Dec 6, 2021
2 parents 2051262 + d6cf44b commit 2798de8
Show file tree
Hide file tree
Showing 19 changed files with 205 additions and 86 deletions.
4 changes: 2 additions & 2 deletions conda.recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ requirements:
- google-auth-httplib2
- google-auth-oauthlib
- pyqt =5
- pwspy >=0.2.8 # Core pws package, available on backmanlab anaconda cloud account.
- mpl_qt_viz >=1.0.9 # Plotting package available on PyPi and the backmanlab anaconda cloud account and conda-forge. Written for this project by Nick Anthony
- pwspy >=0.2.12 # Core pws package, available on backmanlab anaconda cloud account.
- mpl_qt_viz >1.0.9 # Plotting package available on PyPi and the backmanlab anaconda cloud account and conda-forge. Written for this project by Nick Anthony
- descartes
- cachetools >=4
app:
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
'google-auth-httplib2',
'google-auth-oauthlib',
'PyQt5',
'pwspy>=0.2.8', # Core pws package, available on backmanlab anaconda cloud account.
'mpl_qt_viz>=1.0.9', # Plotting package available on PyPi and the backmanlab anaconda cloud account. Written for this project by Nick Anthony
'pwspy>=0.2.12', # Core pws package, available on backmanlab anaconda cloud account.
'mpl_qt_viz>1.0.9', # Plotting package available on PyPi and the backmanlab anaconda cloud account. Written for this project by Nick Anthony
'descartes',
'cachetools>=4'],
package_dir={'': 'src'},
Expand Down
53 changes: 34 additions & 19 deletions src/pwspy_gui/ExtraReflectanceCreator/ERWorkFlow.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with PWSpy. If not, see <https://www.gnu.org/licenses/>.

import dataclasses
import hashlib
import os
from datetime import datetime
Expand All @@ -24,7 +24,7 @@
from PyQt5.QtWidgets import QWidget
from matplotlib import animation

from pwspy.dataTypes import CameraCorrection, Acquisition, ICMetaData, PwsCube
from pwspy.dataTypes import CameraCorrection, Acquisition, PwsMetaData, PwsCube
from pwspy_gui.ExtraReflectanceCreator.widgets.dialog import IndexInfoForm
from pwspy.dataTypes import Roi
from pwspy import dateTimeFormat
Expand All @@ -39,11 +39,17 @@
from mpl_qt_viz.visualizers import PlotNd, DockablePlotWindow
import pathlib as pl

DirectoryDataFrame = t_.NewType("DirectoryDataFrame", pd.DataFrame) # Type alias representing the data frame returned by `scanDirectory`
# Has columns "setting", "cube", "material"


@dataclasses.dataclass
class Directory:
def __init__(self, df: pd.DataFrame, camCorr: CameraCorrection):
self.dataframe = df
self.cameraCorrection = camCorr
"""
Groups together relevant data for a given "System Directory" in the ERCreator raw data collection.
"""
dataframe: DirectoryDataFrame
cameraCorrection: CameraCorrection


def scanDirectory(directory: str) -> Directory:
Expand Down Expand Up @@ -75,28 +81,34 @@ def scanDirectory(directory: str) -> Directory:
m = matMap[filelist[-2]]
file = Acquisition(file).pws.filePath # old pws is saved directly in the "Cell{X}" folder. new pws is saved in "Cell{x}/PWS" the Acquisition class helps us abstract that out and be compatible with both.
rows.append({'setting': s, 'material': m, 'cube': file})
df = pd.DataFrame(rows)
return Directory(df, cam)
df: DirectoryDataFrame = pd.DataFrame(rows)
return Directory(dataframe=df, cameraCorrection=cam)


class DataProvider:
def __init__(self, df: pd.DataFrame, camCorr: CameraCorrection):
self._df = df
self._cameraCorrection = camCorr
self._cubes = None
"""
This object manages caching data and processing new data when it needs to be loaded.
Args:
directory: The Directory object providing a reference to the actual data.
"""
def __init__(self, directory: Directory):
self._df = directory.dataframe
self._cameraCorrection = directory.cameraCorrection
self._cubes: pd.DataFrame = None

def getCubes(self):
def getCubes(self) -> t_.Optional[pd.DataFrame]:
return self._cubes

def getDataFrame(self):
def getDataFrame(self) -> pd.DataFrame:
return self._df

def loadCubes(self, includeSettings: t_.List[str], binning: int, parallelProcessing: bool):
df = self._df[self._df['setting'].isin(includeSettings)]
if binning is None:
args = {'correction': None, 'binning': None}
for cube in df['cube']:
md = ICMetaData.loadAny(cube)
md = PwsMetaData.loadAny(cube)
if md.binning is None:
raise Exception("No binning metadata found. Please specify a binning setting.")
elif md.cameraCorrection is None:
Expand Down Expand Up @@ -182,7 +194,7 @@ def plot(self, includeSettings: t_.List[str], binning: int, parallelProcessing:
print("Select an ROI")
roi = cubes['cube'].sample(n=1).iloc[0].selectLassoROI() # Select an ROI to analyze
cubeDict = cubes.groupby('setting').apply(lambda df: df.groupby('material')['cube'].apply(list).to_dict()).to_dict() # Transform data frame to a dict of dicts of lists for input to `plot`
self.figs.extend(er.plotExtraReflection(cubeDict, theoryR, matCombos, numericalAperture, roi))
self.figs.extend(er.plotExtraReflection(cubeDict, theoryR, matCombos, roi))

def save(self, includeSettings: t_.List[str], binning: int, parallelProcessing: bool, numericalAperture: float, parentWidget: QWidget):
self.loadIfNeeded(includeSettings, binning, parallelProcessing)
Expand All @@ -199,16 +211,19 @@ def save(self, includeSettings: t_.List[str], binning: int, parallelProcessing:
erCube, rExtraDict = er.generateRExtraCubes(combos, theoryR, numericalAperture)
dock = DockablePlotWindow(title=setting)
dock.addWidget(
PlotNd(erCube.data, title='Mean',
PlotNd(erCube.data,
title='Mean',
indices=[range(erCube.data.shape[0]), range(erCube.data.shape[1]),
erCube.wavelengths]),
erCube.wavelengths],
names=('y', 'x', 'lambda')),
title='Mean'
)
for matCombo, rExtraArr in rExtraDict.items():
dock.addWidget(
PlotNd(rExtraArr, title=matCombo,
indices=[range(erCube.data.shape[0]), range(erCube.data.shape[1]),
erCube.wavelengths]),
erCube.wavelengths],
names=('y', 'x', 'lambda')),
title=str(matCombo)
)
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -284,5 +299,5 @@ def directoryChanged(self, directory: str) -> t_.Set[str]:
"""
self.currDir = directory
directory = self.fileStruct[directory]
self.dataprovider = DataProvider(directory.dataframe, directory.cameraCorrection)
self.dataprovider = DataProvider(directory)
return set(self.dataprovider.getDataFrame()['setting'])
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ def getExtraReflectanceMetadata(self) -> pwsdt.ERMetaData:
class PWSRuntimeAnalysisSettings(AbstractRuntimeAnalysisSettings): # Inherit docstring
settings: PWSAnalysisSettings
extraReflectanceMetadata: typing.Optional[pwsdt.ERMetaData]
referenceMetadata: pwsdt.ICMetaData
cellMetadata: typing.List[pwsdt.ICMetaData]
referenceMetadata: pwsdt.PwsMetaData
cellMetadata: typing.List[pwsdt.PwsMetaData]
analysisName: str

def getSaveableSettings(self) -> PWSAnalysisSettings:
Expand All @@ -98,10 +98,10 @@ def getSaveableSettings(self) -> PWSAnalysisSettings:
def getAnalysisName(self) -> str:
return self.analysisName

def getReferenceMetadata(self) -> pwsdt.ICMetaData:
def getReferenceMetadata(self) -> pwsdt.PwsMetaData:
return self.referenceMetadata

def getCellMetadatas(self) -> typing.Sequence[pwsdt.ICMetaData]:
def getCellMetadatas(self) -> typing.Sequence[pwsdt.PwsMetaData]:
return self.cellMetadata

def getExtraReflectanceMetadata(self) -> pwsdt.ERMetaData:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
QInputDialog, QHeaderView

from pwspy_gui.PWSAnalysisApp.sharedWidgets import ScrollableMessageBox
from pwspy.dataTypes import Acquisition, ICMetaData, DynMetaData
from pwspy.dataTypes import Acquisition, PwsMetaData, DynMetaData

from pwspy_gui.PWSAnalysisApp.sharedWidgets.dictDisplayTree import DictDisplayTreeDialog
from pwspy_gui.PWSAnalysisApp.sharedWidgets.tables import NumberTableWidgetItem
Expand Down Expand Up @@ -349,7 +349,7 @@ def _deleteAnalysisByName(self):
else:
ret = ScrollableMessageBox.question(self, "Delete Analysis?",
f"Are you sure you want to delete {anName} from:"
f"\nPWS: {', '.join([os.path.split(i.acquisitionDirectory.filePath)[-1] for i in deletableCells if isinstance(i, ICMetaData)])}"
f"\nPWS: {', '.join([os.path.split(i.acquisitionDirectory.filePath)[-1] for i in deletableCells if isinstance(i, PwsMetaData)])}"
f"\nDynamics: {', '.join([os.path.split(i.acquisitionDirectory.filePath)[-1] for i in deletableCells if isinstance(i, DynMetaData)])}")
if ret == QMessageBox.Yes:
[i.removeAnalysis(anName) for i in deletableCells]
Expand Down Expand Up @@ -485,7 +485,7 @@ def updateReferences(self, state: bool, items: t_.List[CellTableWidgetItem]):

@property
def selectedReferenceMeta(self) -> t_.Optional[Acquisition]:
"""Returns the ICMetadata that have been selected. Return None if nothing is selected."""
"""Returns the PwsMetaData that have been selected. Return None if nothing is selected."""
items: List[ReferencesTableItem] = self.selectedItems()
assert len(items) <= 1
if len(items) == 0:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from ...componentInterfaces import ResultsTableController

if typing.TYPE_CHECKING:
from pwspy.dataTypes import Acquisition, ICMetaData
from pwspy.dataTypes import Acquisition, PwsMetaData
from pwspy.analysis.pws import PWSAnalysisSettings
from pwspy.analysis.warnings import AnalysisWarning

Expand Down Expand Up @@ -135,7 +135,7 @@ def _handleCompilationResults(self, inVal: typing.List[typing.Tuple[Acquisition,


class CompilationSummaryDisplay(QDialog):
def __init__(self, parent: typing.Optional[QWidget], warnings: typing.List[typing.Tuple[ICMetaData, typing.List[typing.Tuple[PWSRoiCompilationResults, typing.Optional[typing.List[AnalysisWarning]]]]]], analysisName: str = '', analysisSettings: PWSAnalysisSettings = None):
def __init__(self, parent: typing.Optional[QWidget], warnings: typing.List[typing.Tuple[PwsMetaData, typing.List[typing.Tuple[PWSRoiCompilationResults, typing.Optional[typing.List[AnalysisWarning]]]]]], analysisName: str = '', analysisSettings: PWSAnalysisSettings = None):
super().__init__(parent=parent)
self.setWindowTitle("Compilation Summary")
layout = QVBoxLayout()
Expand All @@ -146,7 +146,7 @@ def __init__(self, parent: typing.Optional[QWidget], warnings: typing.List[typin
self._addWarnings(warnings)
self.show()

def _addWarnings(self, warnings: typing.List[typing.Tuple[ICMetaData, typing.List[typing.Tuple[ConglomerateCompilerResults, typing.Optional[typing.List[AnalysisWarning]]]]]]):
def _addWarnings(self, warnings: typing.List[typing.Tuple[PwsMetaData, typing.List[typing.Tuple[ConglomerateCompilerResults, typing.Optional[typing.List[AnalysisWarning]]]]]]):
for meta, roiList in warnings:
item = QTreeWidgetItem(self.warningTree)
item.setText(0, meta.filePath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ def _plotOpd(self):
fig, ax = plt.subplots()
ax.plot(self.results.pws.opdIndex, self.results.pws.opd)
fig.suptitle(f"{self.cellPathLabel.text()}/Cell{self.cellNumLabel.text()}")
ax.set_ylabel("Amplitude")
ax.set_xlabel("OPD (um)")
fig.show()


Expand Down
21 changes: 20 additions & 1 deletion src/pwspy_gui/PWSAnalysisApp/_roiManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,26 @@ def updateRoi(self, roiFile: pwsdt.RoiFile, roi: pwsdt.Roi):
self.roiUpdated.emit(roiFile)

def createRoi(self, acq: pwsdt.Acquisition, roi: pwsdt.Roi, roiName: str, roiNumber: int, overwrite: bool = False) -> pwsdt.RoiFile:
roiFile = acq.saveRoi(roiName, roiNumber, roi, overwrite=overwrite)
"""
Args:
acq: The acquisition to save the ROI to
roi: The ROI to save.
roiName: The name to save the ROI as.
roiNumber: The number to save the ROI as.
overwrite: Whether to overwrite existing ROIs with conflicting name/number combo.
Returns:
A reference to the created ROIFile
Raises:
OSError: If `overwrite` is false and an ROIFile for this name and number already exists.
"""
try:
roiFile = acq.saveRoi(roiName, roiNumber, roi, overwrite=overwrite)
except OSError as e:
raise e
self._cache[self._getCacheKey(roiFile)] = roiFile
self.roiCreated.emit(roiFile, overwrite)
return roiFile
Expand Down
6 changes: 3 additions & 3 deletions src/pwspy_gui/PWSAnalysisApp/_taskManagers/analysisManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from pwspy.analysis.pws import PWSAnalysis
from pwspy_gui.PWSAnalysisApp._dockWidgets.AnalysisSettingsDock.runtimeSettings import PWSRuntimeAnalysisSettings, DynamicsRuntimeAnalysisSettings
from pwspy.analysis.warnings import AnalysisWarning
from pwspy.dataTypes import ICRawBase, ICMetaData, DynMetaData
from pwspy.dataTypes import ICRawBase, PwsMetaData, DynMetaData
from pwspy.utility.fileIO import loadAndProcess
if typing.TYPE_CHECKING:
from pwspy_gui.PWSAnalysisApp.App import PWSApp
Expand Down Expand Up @@ -90,7 +90,7 @@ def runSingle(self, anSettings: AbstractRuntimeAnalysisSettings) -> Tuple[str, A
if correctionsOk:
if isinstance(anSettings, PWSRuntimeAnalysisSettings):
AnalysisClass = PWSAnalysis
refMeta: ICMetaData
refMeta: PwsMetaData
elif isinstance(anSettings, DynamicsRuntimeAnalysisSettings):
AnalysisClass = DynamicsAnalysis
refMeta: DynMetaData
Expand Down Expand Up @@ -180,7 +180,7 @@ def __init__(self, cellMetas, analysis, anName, cameraCorrection, userSpecifiedB
def run(self):
try:
self.warnings = loadAndProcess(self.cellMetas, processorFunc=self._process, initArgs=[self.analysis, self.anName, self.cameraCorrection, self.userSpecifiedBinning],
parallel=self.parallel, initializer=self._initializer) # Returns a list of Tuples, each tuple containing a list of warnings and the ICmetadata to go with it.
parallel=self.parallel, initializer=self._initializer) # Returns a list of Tuples, each tuple containing a list of warnings and the PwsMetaData to go with it.
except Exception as e:
import traceback
trace = traceback.format_exc()
Expand Down
6 changes: 3 additions & 3 deletions src/pwspy_gui/PWSAnalysisApp/dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

if typing.TYPE_CHECKING:
from typing import Optional, List, Tuple
from pwspy.dataTypes import ICMetaData
from pwspy.dataTypes import PwsMetaData
from pwspy.analysis.compilation import PWSRoiCompilationResults
from pwspy.analysis.pws import PWSAnalysisSettings
from pwspy.analysis.warnings import AnalysisWarning
Expand Down Expand Up @@ -84,7 +84,7 @@ def show(self):


class AnalysisSummaryDisplay(QDialog):
def __init__(self, parent: Optional[QWidget], warnings: List[Tuple[List[AnalysisWarning], ICMetaData]], analysisName: str = '', analysisSettings: PWSAnalysisSettings = None):
def __init__(self, parent: Optional[QWidget], warnings: List[Tuple[List[AnalysisWarning], PwsMetaData]], analysisName: str = '', analysisSettings: PWSAnalysisSettings = None):
super().__init__(parent=parent)
self.analysisName = analysisName
self.analysisSettings = analysisSettings
Expand All @@ -100,7 +100,7 @@ def __init__(self, parent: Optional[QWidget], warnings: List[Tuple[List[Analysis
self.setWindowTitle(f"Analysis Summary: {analysisName}")
self.show()

def _addWarnings(self, warnings: List[Tuple[List[AnalysisWarning],ICMetaData]]):
def _addWarnings(self, warnings: List[Tuple[List[AnalysisWarning],PwsMetaData]]):
for cellWarns, cell in warnings:
item = QTreeWidgetItem(self.warnList)
item.setText(0, cell.filePath)
Expand Down
Loading

0 comments on commit 2798de8

Please sign in to comment.