Skip to content

Commit

Permalink
re #24: I added the ability to save the sample data to a csv
Browse files Browse the repository at this point in the history
  • Loading branch information
16djm10 committed Nov 1, 2022
1 parent c70c645 commit a9b299f
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 74 deletions.
132 changes: 76 additions & 56 deletions BroadbandSpecModule/BroadbandSpecModule.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from array import array
from calendar import SATURDAY
import logging
from __main__ import vtk, qt, ctk, slicer
from slicer.ScriptedLoadableModule import *
from slicer.util import VTKObservationMixin
import sklearn
import numpy as np
import os
try:
from joblib import load
except:
Expand Down Expand Up @@ -116,20 +118,19 @@ def setup(self):

# *** When these change, simply update the parameter node
self.ui.dataClassSelector.connect('currentIndexChanged(int)', self.onDataClassSelectorChanged)
self.ui.saveLocationSelector.connect('currentPathChanged(QString)', self.onSaveLocationSelectorChanged)
# add the options cancer and normal to the data class selector
self.ui.dataClassSelector.addItem("Cancer")
self.ui.dataClassSelector.addItem("Normal")
self.ui.sampleDurationSelector.connect('currentIndexChanged(int)', self.onSampleDurationSelectorChanged)
# add the options 0.5, 1, 2 to the sample duration selector
self.ui.sampleDurationSelector.addItem(0.5)
self.ui.sampleDurationSelector.addItem(1)
self.ui.sampleDurationSelector.addItem(2)

self.ui.sampleRateSelector.connect('currentIndexChanged(int)', self.onSampleRateSelectorChanged)
self.ui.samplePerSecondSelector.connect('currentIndexChanged(int)', self.onSamplePerSecondSelectorChanged)
# add option 1, 10,100 to the sample rate selector
self.ui.sampleRateSelector.addItem(1)
self.ui.sampleRateSelector.addItem(10)
self.ui.sampleRateSelector.addItem(100)
self.ui.samplePerSecondSelector.addItem(10)
self.ui.samplePerSecondSelector.addItem(100)
self.ui.collectSampleButton.connect('clicked(bool)', self.onCollectSampleButtonClicked)

# Make sure parameter node is initialized (needed for module reload)
Expand All @@ -148,10 +149,10 @@ def onSampleDurationSelectorChanged(self):
sampleDuration = self.ui.sampleDurationSelector.currentText
parameterNode.SetParameter(self.logic.SAMPLE_DURATION, sampleDuration)

def onSampleRateSelectorChanged(self):
def onSamplePerSecondSelectorChanged(self):
self.updateParameterNodeFromGUI()
parameterNode = self.logic.getParameterNode()
sampleRate = self.ui.sampleRateSelector.currentText
sampleRate = self.ui.samplePerSecondSelector.currentText
parameterNode.SetParameter(self.logic.SAMPLE_PER_SECOND, sampleRate)

def onCollectSampleButtonClicked(self):
Expand Down Expand Up @@ -195,6 +196,15 @@ def onConnectButtonClicked(self):
print('Connector node stopped')
self.ui.connectButton.text = 'Connect'

def onSaveLocationSelectorChanged(self):
self.updateParameterNodeFromGUI()
# get path from the selector
path = self.ui.saveLocationSelector.currentPath
# get parameter node
parameterNode = self.logic.getParameterNode()
# set the path in the parameter node
parameterNode.SetParameter(self.logic.SAVE_LOCATION, path)

def onSpectrumImageChanged(self):
self.updateParameterNodeFromGUI()

Expand Down Expand Up @@ -303,8 +313,11 @@ def initializeParameterNode(self):

# If no model path is selected, select the default one
if self._parameterNode.GetNodeReference(self.logic.MODEL_PATH) is None:
defaultModelPath = 'C:/Spectroscopy_TrackedTissueSensing/TrainedModels/KNN_PorkVsBeefTest.joblib' # Hardcoded path
self._parameterNode.SetParameter(self.logic.MODEL_PATH, defaultModelPath)
self._parameterNode.SetParameter(self.logic.MODEL_PATH, self.logic.DEFAULT_MODEL_PATH)

# Add a default save location if none exists
if self._parameterNode.GetNodeReference(self.logic.SAVE_LOCATION) is None:
self._parameterNode.SetParameter(self.logic.SAVE_LOCATION, self.logic.DEFAULT_SAVE_LOCATION)

def updateGUIFromParameterNode(self, caller=None, event=None):
"""
Expand Down Expand Up @@ -338,6 +351,11 @@ def updateGUIFromParameterNode(self, caller=None, event=None):
if self.ui.modelFileSelector.currentPath == '':
# set the current path to whatever is stored in the parameter node
self.ui.modelFileSelector.currentPath = self._parameterNode.GetParameter(self.logic.MODEL_PATH)

# Update the save location to be the last selection
if self.ui.saveLocationSelector.currentPath == '':
# set the current path to whatever is stored in the parameter node
self.ui.saveLocationSelector.currentPath = self._parameterNode.GetParameter(self.logic.SAVE_LOCATION)

# All the GUI updates are done
self._updatingGUIFromParameterNode = False
Expand Down Expand Up @@ -420,16 +438,18 @@ class BroadbandSpecModuleLogic(ScriptedLoadableModuleLogic,VTKObservationMixin):
# NAMES
INPUT_VOLUME = "InputVolume"
OUTPUT_TABLE = "OutputTable"
CLASSIFICATION = "Classification"
MODEL_PATH = "ModelPath"
CLASSIFICATION = "Classification"
CLASS_LABEL_0 = "ClassLabel0"
CLASS_LABEL_1 = "ClassLabel1"
CLASS_LABEL_NONE = "WeakSignal"
SCANNING_STATE = 'Scanning State'
PLOTTING_STATE = 'Plotting State'
SAMPLE_DURATION = "SampleDuration"
SAMPLE_PER_SECOND = "SampleRate"
DATA_CLASS = "DataClass"
CLICK_COUNT = 'Click Count'
SAMPLE_DURATION = "Sample Duration"
SAMPLE_PER_SECOND = "Sample Rate"
DATA_CLASS = "Data Class"
SAVE_LOCATION = 'Save Location'

# ROLES
POINTLIST_GREEN_WORLD = 'pointList_Green_World'
Expand All @@ -443,6 +463,8 @@ class BroadbandSpecModuleLogic(ScriptedLoadableModuleLogic,VTKObservationMixin):

# Constants
DISTANCE_THRESHOLD = 2 # in mm
DEFAULT_SAVE_LOCATION = os.path.join('C:\Spectroscopy_TrackedTissueSensing\data', 'Nov2022_skinTestData')
DEFAULT_MODEL_PATH = os.path.join('C:\Spectroscopy_TrackedTissueSensing\TrainedModels', 'KNN_WhiteVsBlue2.joblib')

def __init__(self):
"""
Expand Down Expand Up @@ -611,9 +633,7 @@ def recordSample(self):
parameterNode = self.getParameterNode()
seqBrowserNode.RemoveAllProxyNodes()
image.EndModify(0) # when the second seq is created I think it modifys the first and then the second is ended. When things stop modifying call this.
'''

# Instantiate sequenceLogic
sequenceLogic = slicer.modules.sequences.logic()
# Only call this once, check to see if the sequence already exists
Expand All @@ -625,56 +645,56 @@ def recordSample(self):
# Print clearing sequence node
sequenceNode.RemoveAllDataNodes()

browserNode.SetRecording(sequenceNode, True)
browserNode.SetPlayback(sequenceNode, True)
browserNode.SetRecordingActive(True)
timer = qt.QTimer()
# NOTE: singleShot will proceed with the next lines of code before the timer is done

timer.singleShot(float(sampleDuration)*1000+50, lambda: browserNode.SetRecordingActive(False)) # can create a new function here for print statements


seqNode = parameterNode.GetNodeReference(self.SAMPLE_SEQUENCE)


# Get node by ID
# seq = slicer.mrmlScene.GetNodeByID(sequenceNode.GetID())
# seq = slicer.mrmlScene.GetNodeByID("vtkMRMLSequenceNode2")
# delete the sequence from the scene
# slicer.mrmlScene.RemoveNode(sequenceNode)

'''
Tamas: This script was to record lots of sequences
sequenceLogic = slicer.modules.sequences.logic()
sequenceNode = sequenceLogic.AddSynchronizedNode(None, image_imageNode, seqBrowserNode) # Do not create a sequence node.
browserNode.SetRecording(sequenceNode, True)
browserNode.SetPlayback(sequenceNode, True)
# Start recording
# set the fps
browserNode.SetPlaybackRateFps(float(sampleFrequency))
browserNode.SetRecordingActive(True)
# To turn it off after a given time, use a Qtimer
timer = qt.QTimer()
timer.singleShot(1000, lambda: browserNode.SetRecordingActive(False))
# Google python string formats
'''
# folder = 'C:/Spectroscopy_TrackedTissueSensing/broadbandTestData/' + dataLabel + '/'
# NOTE: singleShot will proceed with the next lines of code before the timer is done

# for idx in range(sampleSeqNode.GetNumberOfDataNodes()): # fill up the whole array first then save once.
# volumeNode = sampleSeqNode.GetNthDataNode(idx)
# specArray = slicer.util.arrayFromVolume(volumeNode)
# specArray = np.squeeze(specArray)
# specArray = np.transpose(specArray)
# if idx <= 9:# There is a
# num = '0'+str(idx)
# else:
# num = str(idx)
# timer.singleShot(float(sampleDuration)*1000+50, lambda: browserNode.SetRecordingActive(False)) # can create a new function here for print statements
timer.singleShot(float(sampleDuration)*1000+50, lambda: self.saveSample())

# np.savetxt(folder + dataLabel + num + '.csv', specArray, delimiter=',') # Switch to Os.path.join

def saveSample(self):

pass
# get parameters
parameterNode = self.getParameterNode()
dataLabel = parameterNode.GetParameter(self.DATA_CLASS)
sampleDuration = parameterNode.GetParameter(self.SAMPLE_DURATION)
# Stop the timer
browserNode = parameterNode.GetNodeReference(self.SAMPLE_SEQ_BROWSER)
browserNode.SetRecordingActive(False)
# Get the sequence node
sequenceNode = parameterNode.GetNodeReference(self.SAMPLE_SEQUENCE)
# Save the sequence to a csv
savePath = parameterNode.GetParameter(self.SAVE_LOCATION)
savePath = os.path.join(savePath, dataLabel)
# Loop through the sequence
sequenceLength = sequenceNode.GetNumberOfDataNodes()
# Format the empty array
# Get the length of a spectrum
spectrumArray = slicer.util.arrayFromVolume(sequenceNode.GetNthDataNode(0))
SpectrumLength = spectrumArray.shape[2]
# Create the 2D array
spectrumArray2D = np.zeros((sequenceLength + 1, SpectrumLength + 1))
# Fill the 2D array
# create a time vector using the sampleDuration
timeVector = np.linspace(0, float(sampleDuration), sequenceLength)
# concatenate the time vector to the spectrum array
spectrumArray2D[1:,0] = timeVector
# print shape of the array
print(spectrumArray2D.shape)
for i in range(sequenceLength):
# Get a spectrum as an array
spectrumArray = np.squeeze(slicer.util.arrayFromVolume(sequenceNode.GetNthDataNode(i)))
spectrumArray2D[i+1,1:] = spectrumArray[1,:]
# Save the array to a csv
clickCount = parameterNode.GetParameter(self.CLICK_COUNT)
np.savetxt(savePath + '.csv', spectrumArray2D[1:,:], delimiter=",")
# np.savetxt(savePath + clickCount + '.csv', spectrumArray2D[1:,:], delimiter=",")



def addControlPointToToolTip(self):
Expand Down
62 changes: 44 additions & 18 deletions BroadbandSpecModule/Resources/UI/BroadbandSpecModule.ui
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<property name="text">
<string>Setup</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_1">
Expand Down Expand Up @@ -120,19 +123,22 @@
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="enablePlottingButton">
<property name="text">
<string>Enable Plotting</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="enablePlottingButton">
<property name="text">
<string>Enable Plotting</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="ctkCollapsibleButton" name="dataCollectionSection_2">
<property name="enabled">
Expand All @@ -148,11 +154,14 @@
<item row="1" column="1">
<widget class="QPushButton" name="scanButton">
<property name="text">
<string>Start Scanning</string>
<string>Start continuous scan</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="1">
Expand All @@ -175,7 +184,7 @@
<item row="0" column="1">
<widget class="QPushButton" name="addControlPointButton">
<property name="text">
<string>Add Control Point at Tool Tip</string>
<string>Point Scan</string>
</property>
</widget>
</item>
Expand Down Expand Up @@ -203,26 +212,43 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_20">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Sampling duration (seconds)</string>
<string>Save Location</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="ctkPathLineEdit" name="saveLocationSelector">
<property name="enabled">
<bool>true</bool>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="sampleDurationSelector"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_21">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Spectra per second</string>
<string>Sampling duration (seconds)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="sampleRateSelector"/>
<item row="3" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Samples Per Second</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="samplePerSecondSelector"/>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="collectSampleButton">
<property name="text">
<string>Collect Sample</string>
Expand Down
Binary file removed TrainedModels/KNN_BlueVsWhite.joblib
Binary file not shown.
Binary file removed TrainedModels/KNN_CardboardVsTeaBox.joblib
Binary file not shown.
Binary file removed TrainedModels/KNN_TestModel.joblib
Binary file not shown.
Binary file removed TrainedModels/WorkedReallyWell/my_checkpoint.pth.tar
Binary file not shown.

0 comments on commit a9b299f

Please sign in to comment.