diff --git a/Source/Processors/Channel.cpp b/Source/Processors/Channel.cpp
index 19bf8e2222b08e06384104f381e00e8442c1a768..210ca9ac3c84c3650019fc0aaaac53c14added1e 100644
--- a/Source/Processors/Channel.cpp
+++ b/Source/Processors/Channel.cpp
@@ -61,6 +61,11 @@ String Channel::getName()
 
 }
 
+void Channel::setName(String name_)
+{
+    name = name_;
+}
+
 void Channel::reset()
 {
     createDefaultName();
diff --git a/Source/Processors/Channel.h b/Source/Processors/Channel.h
index af30c38c8cd32e3fa0225e9218625422dd049b9a..a32c6cb93161372784abad3f99a69ef582c20fca 100644
--- a/Source/Processors/Channel.h
+++ b/Source/Processors/Channel.h
@@ -61,6 +61,9 @@ public:
     /** Returns the name of a given channel. */
     String getName();
 
+    /** Sets the name of a given channel. */
+    void setName(String);
+
     /** Restores the default settings for a given channel. */
     void reset();
 
diff --git a/Source/Processors/ChannelMappingNode.cpp b/Source/Processors/ChannelMappingNode.cpp
index 05e691e6522f18f673b43dd9b453aa680644bd6b..4388f0879c3066987a902ef5e4a39202dba35e64 100644
--- a/Source/Processors/ChannelMappingNode.cpp
+++ b/Source/Processors/ChannelMappingNode.cpp
@@ -32,6 +32,13 @@ ChannelMappingNode::ChannelMappingNode()
 {
 	referenceArray.resize(1024); // make room for 1024 channels
 	channelArray.resize(1024);
+
+	for (int i = 0; i < referenceArray.size(); i++)
+	{
+		referenceArray.set(i, -1);
+		channelArray.set(i, i);
+	}
+
 }
 
 ChannelMappingNode::~ChannelMappingNode()
@@ -52,7 +59,9 @@ AudioProcessorEditor* ChannelMappingNode::createEditor()
 
 void ChannelMappingNode::updateSettings()
 {
-	channelBuffer.setSize(getNumInputs(), 10000);
+	if (getNumInputs() > 0)
+		channelBuffer.setSize(getNumInputs(), 10000);
+
 }
 
 
@@ -74,10 +83,10 @@ void ChannelMappingNode::process(AudioSampleBuffer& buffer,
                             int& nSamples)
 {
 
-	// copy everything into the channel buffer
-	channelBuffer.setDataToReferTo(buffer.getArrayOfChannels(), 
-								   buffer.getNumChannels(),
-								   buffer.getNumSamples());
+	// use copy constructor to set the data to refer to
+	channelBuffer = buffer; //.setDataToReferTo(buffer.getArrayOfChannels(), 
+							//	   buffer.getNumChannels(),
+						//		   buffer.getNumSamples());
 
 	// copy it back into the buffer according to the channel mapping
 	buffer.clear();
@@ -90,7 +99,7 @@ void ChannelMappingNode::process(AudioSampleBuffer& buffer,
                        channelArray[i], // sourceChannel
                        0, // sourceStartSample
                        nSamples, // numSamples
-                       1.0f // gain to apply to source (positive)
+                       1.0f // gain to apply to source (positive for original signal)
                        );
 
 	}
diff --git a/Source/Processors/DataThreads/DataThread.h b/Source/Processors/DataThreads/DataThread.h
index 03a18aa30679b23f4b10f207d65d0926439a6f0e..72c4aa45cd463291169279c96526c0ca5b90a484 100755
--- a/Source/Processors/DataThreads/DataThread.h
+++ b/Source/Processors/DataThreads/DataThread.h
@@ -93,6 +93,9 @@ public:
         return 0;
     }
 
+    /** Changes the names of channels, if the thread needs custom names. */
+    virtual void updateChannelNames() { }
+
     SourceNode* sn;
 
     int16 eventCode;
diff --git a/Source/Processors/DataThreads/RHD2000Thread.cpp b/Source/Processors/DataThreads/RHD2000Thread.cpp
index ee53e742b4d7b5737504e6667011f5341da0f655..66cbc03efba3cb614591831ea6863a23f6e1110c 100644
--- a/Source/Processors/DataThreads/RHD2000Thread.cpp
+++ b/Source/Processors/DataThreads/RHD2000Thread.cpp
@@ -28,7 +28,7 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn), isTransmitting(fa
     fastSettleEnabled(false), chipRegisters(30000.0f), dspEnabled(true), boardSampleRate(30000.0f),
     desiredDspCutoffFreq(0.5f), desiredUpperBandwidth(7500.0f), desiredLowerBandwidth(1.0f),
     savedSampleRateIndex(16), audioOutputL(-1), audioOutputR(-1), dacOutputShouldChange(false),
-    acquireAdcChannels(false),
+    acquireAdcChannels(false), acquireAuxChannels(true),
     cableLengthPortA(0.914f), cableLengthPortB(0.914f), cableLengthPortC(0.914f), cableLengthPortD(0.914f) // default is 3 feet (0.914 m)
 {
     evalBoard = new Rhd2000EvalBoard;
@@ -407,6 +407,58 @@ int RHD2000Thread::getNumChannels()
         return 1; // to prevent crashing with 0 channels
 }
 
+void RHD2000Thread::updateChannelNames()
+{
+
+    int chNum = -1;
+
+    for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
+    {
+    
+        for (int j = 0; j < numChannelsPerDataStream[i]; j++)
+        {
+            chNum++;
+
+            sn->channels[chNum]->setName(String(chNum));
+        }
+    }
+
+    if (acquireAuxChannels)
+    {
+        for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
+        {
+        
+            for (int j = 0; j < 3; j++)
+            {
+                
+                chNum++;
+
+                String chName = "AUX";
+                chName += (j+1);
+
+              // this is causing a seg fault for some reason:
+              //  sn->channels[chNum]->setName(chName);
+            }
+        }
+    }
+
+
+    if (acquireAdcChannels)
+    {
+        for (int j = 0; j < 8; j++)
+        {
+            chNum++;
+
+            String chName = "ADC";
+            chName += (j+1);
+
+          //  sn->channels[chNum]->setName(chName);
+        }
+    }        
+
+}
+
+
 int RHD2000Thread::getNumEventChannels()
 {
     return 16; // 8 inputs, 8 outputs
@@ -826,6 +878,7 @@ bool RHD2000Thread::updateBuffer()
                 int streamNumber = -1;
                 int channel = -1;
 
+                // do the neural data channels first
                 for (int dataStream = 0; dataStream < MAX_NUM_DATA_STREAMS; dataStream++)
                 {
                     if (numChannelsPerDataStream[dataStream] > 0)
@@ -842,48 +895,64 @@ bool RHD2000Thread::updateBuffer()
                             thisSample[channel] = float(value-32768)*0.195f;
                         }
 					
-						// TEMPORARILY DISABLED -- causing problems
-						if (samp % 4 == 1) { // every 4th sample should have auxiliary input data
-						
-							channel++;
-							thisSample[channel] = 0.0374 *
-							     float(dataBlock->auxiliaryData[dataStream][1][samp+0]);
-							auxBuffer[channel]=thisSample[channel];
+					}
 
-							channel++;
-							thisSample[channel] = 0.0374 *
-							     float(dataBlock->auxiliaryData[dataStream][1][samp+1]);
-							auxBuffer[channel]=thisSample[channel];
+				}
 
-						
-							channel++;
-							thisSample[channel] = 0.0374 *
-							     float(dataBlock->auxiliaryData[dataStream][1][samp+2]);
-							auxBuffer[channel]=thisSample[channel];
+                streamNumber = -1;
 
-						} else{ // repeat last values from buffer
-							channel++;
-							thisSample[channel] = auxBuffer[channel];
-							channel++;
-							thisSample[channel] = auxBuffer[channel];
-							channel++;
-							thisSample[channel] = auxBuffer[channel];
-						}
+                // then do the ADC channels
+                for (int dataStream = 0; dataStream < MAX_NUM_DATA_STREAMS; dataStream++)
+                {
+                    if (numChannelsPerDataStream[dataStream] > 0)
+                    {
+                        streamNumber++;
+
+                        if (samp % 4 == 1) { // every 4th sample should have auxiliary input data
+                        
+                            channel++;
+                            thisSample[channel] = 0.0374 *
+                                 float(dataBlock->auxiliaryData[dataStream][1][samp+0]);
+
+                            auxBuffer[channel]=thisSample[channel];
+
+                            channel++;
+                            thisSample[channel] = 0.0374 *
+                                 float(dataBlock->auxiliaryData[dataStream][1][samp+1]);
+
+                            auxBuffer[channel]=thisSample[channel];
+
+                        
+                            channel++;
+                            thisSample[channel] = 0.0374 *
+                                 float(dataBlock->auxiliaryData[dataStream][1][samp+2]);
+
+                            auxBuffer[channel]=thisSample[channel];
+
+                        } else{ // repeat last values from buffer
 
-                        if (acquireAdcChannels)
-                        {
-                            for (int adcChan = 0; adcChan < 8; ++adcChan) {
-                            
                             channel++;
-                            // ADC waveform units = volts
-                             thisSample[channel] = 
-                               0.000050354 * float(dataBlock->boardAdcData[adcChan][samp]);
-                            }
+                            thisSample[channel] = auxBuffer[channel];
+                            channel++;
+                            thisSample[channel] = auxBuffer[channel];
+                            channel++;
+                            thisSample[channel] = auxBuffer[channel];
                         }
-						
-					}
+                    }
 
-				}
+                }
+
+                // finally, loop through ADC channels if necessary
+                if (acquireAdcChannels)
+                {
+                    for (int adcChan = 0; adcChan < 8; ++adcChan) {
+                    
+                    channel++;
+                    // ADC waveform units = volts
+                     thisSample[channel] = 
+                       0.000050354 * float(dataBlock->boardAdcData[adcChan][samp]);
+                    }
+                }
 				// std::cout << channel << std::endl;
 
 				timestamp = dataBlock->timeStamp[samp];
diff --git a/Source/Processors/DataThreads/RHD2000Thread.h b/Source/Processors/DataThreads/RHD2000Thread.h
index 71f77d7ceb3c249904a43f8fcdec17f2e4d07cf8..47faa406f3c77257451d7080818bf473bade459b 100644
--- a/Source/Processors/DataThreads/RHD2000Thread.h
+++ b/Source/Processors/DataThreads/RHD2000Thread.h
@@ -82,6 +82,8 @@ public:
 
     bool isAcquisitionActive();
 
+    void updateChannelNames();
+
 private:
 
     ScopedPointer<Rhd2000EvalBoard> evalBoard;
@@ -104,6 +106,7 @@ private:
 
     bool dacOutputShouldChange;
     bool acquireAdcChannels;
+    bool acquireAuxChannels;
 
     bool fastSettleEnabled;
 
diff --git a/Source/Processors/Editors/ChannelMappingEditor.cpp b/Source/Processors/Editors/ChannelMappingEditor.cpp
index 6a2d946419be5598b784db0bebae227f11327720..4f7faf24396ee598c6d1427456c8e56e1c8f1e5d 100644
--- a/Source/Processors/Editors/ChannelMappingEditor.cpp
+++ b/Source/Processors/Editors/ChannelMappingEditor.cpp
@@ -34,18 +34,17 @@ ChannelMappingEditor::ChannelMappingEditor(GenericProcessor* parentNode, bool us
 {
     desiredWidth = 340;
 
-    ElectrodeEditorButton* e1 = new ElectrodeEditorButton("MAPPING",Font("Small Text",14,Font::plain));
-    e1->addListener(this);
-    addAndMakeVisible(e1);
-    e1->setBounds(15,110,80,10);
-    e1->setToggleState(true, false);
-    electrodeEditorButtons.add(e1);
-
-    ElectrodeEditorButton* e2 = new ElectrodeEditorButton("REF",Font("Small Text",14,Font::plain));
-    e2->addListener(this);
-    addAndMakeVisible(e2);
-    e2->setBounds(100,110,50,10);
-    electrodeEditorButtons.add(e2);
+    mappingButton = new ElectrodeEditorButton("MAPPING",Font("Small Text",14,Font::plain));
+    mappingButton->addListener(this);
+    addAndMakeVisible(mappingButton);
+    mappingButton->setBounds(15,110,80,10);
+    mappingButton->setToggleState(true, false);
+
+    referenceButton = new ElectrodeEditorButton("REF",Font("Small Text",14,Font::plain));
+    referenceButton->addListener(this);
+    addAndMakeVisible(referenceButton);
+    referenceButton->setBounds(100,110,50,10);
+    referenceButton->setToggleState(false, false);
 
     channelSelector->setRadioStatus(true);
 
@@ -104,7 +103,7 @@ void ChannelMappingEditor::createElectrodeButtons(int numNeeded)
 
         channelArray.add(i+1);
 
-        if (column%16 == 0)
+        if (column % 16 == 0)
         {
             column = 0;
             row++;
@@ -119,28 +118,34 @@ void ChannelMappingEditor::createElectrodeButtons(int numNeeded)
 void ChannelMappingEditor::buttonEvent(Button* button)
 {
 
-	if (button == electrodeEditorButtons[0]) // mapping
+	if (button == mappingButton) // mapping
 	{
+        std::cout << "Mapping button clicked." << std::endl;
 
-		electrodeEditorButtons[1]->setToggleState(false, false);
+		referenceButton->setToggleState(false, false);
+        mappingButton->setToggleState(true, false);
 
 		for (int i = 0; i < electrodeButtons.size(); i++)
 		{
 			electrodeButtons[i]->setRadioGroupId(999);
 			electrodeButtons[i]->setChannelNum(channelArray[i]);
-			 electrodeButtons[i]->repaint();
+			electrodeButtons[i]->repaint();
 		}
 
 	}
-	 else if (button == electrodeEditorButtons[1]) // reference
+	 else if (button == referenceButton) // reference
 	{
-		electrodeEditorButtons[0]->setToggleState(false, false);
+
+        std::cout << "Reference button clicked." << std::endl;
+
+		mappingButton->setToggleState(false, false);
+        referenceButton->setToggleState(true, false);
 
 		for (int i = 0; i < electrodeButtons.size(); i++)
 		{
 			electrodeButtons[i]->setRadioGroupId(0);
 			electrodeButtons[i]->setChannelNum(referenceArray[i]);
-			 electrodeButtons[i]->repaint();
+			electrodeButtons[i]->repaint();
 		}
 
 
@@ -161,6 +166,9 @@ void ChannelMappingEditor::buttonEvent(Button* button)
 
 	}
 
+    std::cout << "Reference button state: " << referenceButton->getToggleState() << std::endl;
+    std::cout << "Mapping button state: " << mappingButton->getToggleState() << std::endl;
+
 }
 
 void ChannelMappingEditor::channelChanged(int chan)
@@ -174,7 +182,7 @@ void ChannelMappingEditor::channelChanged(int chan)
 
             getProcessor()->setCurrentChannel(i);
 
-            if (electrodeEditorButtons[1]->getToggleState()) // reference
+            if (referenceButton->getToggleState()) // reference
             {
             	referenceArray.set(i,chan);
 
diff --git a/Source/Processors/Editors/ChannelMappingEditor.h b/Source/Processors/Editors/ChannelMappingEditor.h
index 0ddde7119fa9aea18d4446c3db8ae0f5964f6b0a..46b7a499d8f9e453cccf8f63cafbab403e3c538a 100644
--- a/Source/Processors/Editors/ChannelMappingEditor.h
+++ b/Source/Processors/Editors/ChannelMappingEditor.h
@@ -60,7 +60,8 @@ public:
 private:
 
  	OwnedArray<ElectrodeButton> electrodeButtons;
- 	OwnedArray<ElectrodeEditorButton> electrodeEditorButtons;
+ 	ScopedPointer<ElectrodeEditorButton> referenceButton;
+ 	ScopedPointer<ElectrodeEditorButton> mappingButton;
 
  	Array<int> channelArray;
  	Array<int> referenceArray;
diff --git a/Source/Processors/Editors/SpikeDetectorEditor.cpp b/Source/Processors/Editors/SpikeDetectorEditor.cpp
index 20bfdee9d222af90d6e318903483ca9535adf8a0..92ba610036d18777affc392b3acb701230568e03 100755
--- a/Source/Processors/Editors/SpikeDetectorEditor.cpp
+++ b/Source/Processors/Editors/SpikeDetectorEditor.cpp
@@ -443,6 +443,8 @@ void SpikeDetectorEditor::labelTextChanged(Label* label)
         electrodeTypes->setText(currentText += "s");
     }
 
+    getEditorViewport()->makeEditorVisible(this, false, true);
+
 }
 
 void SpikeDetectorEditor::comboBoxChanged(ComboBox* comboBox)
diff --git a/Source/Processors/Editors/VisualizerEditor.cpp b/Source/Processors/Editors/VisualizerEditor.cpp
index 4ae16d93a285fad2ba61b2627773a74e8035eb6d..ff432a7bfd4031996702babf17eb177bf18be598 100755
--- a/Source/Processors/Editors/VisualizerEditor.cpp
+++ b/Source/Processors/Editors/VisualizerEditor.cpp
@@ -170,6 +170,7 @@ void VisualizerEditor::buttonEvent(Button* button)
         {
 
             canvas = createNewCanvas();
+            canvas->update();
 
             if (isPlaying)
                 canvas->beginAnimation();
diff --git a/Source/Processors/ProcessorGraph.cpp b/Source/Processors/ProcessorGraph.cpp
index 2c0a3707d99c7c6f97b1566a9214e20ea624bf3d..fa997e55df66f1858981c0896e679b295974b26a 100644
--- a/Source/Processors/ProcessorGraph.cpp
+++ b/Source/Processors/ProcessorGraph.cpp
@@ -34,6 +34,7 @@
 #include "RecordNode.h"
 #include "ResamplingNode.h"
 #include "ReferenceNode.h"
+#include "ChannelMappingNode.h"
 #include "AudioResamplingNode.h"
 #include "SignalGenerator.h"
 #include "SourceNode.h"
@@ -503,6 +504,11 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip
             std::cout << "Creating a new digital reference." << std::endl;
             processor = new ReferenceNode();
         }
+        else if (subProcessorType.equalsIgnoreCase("Channel Map"))
+        {
+            std::cout << "Creating a new channel mapping node." << std::endl;
+            processor = new ChannelMappingNode();
+        }
 
         sendActionMessage("New filter node created.");
 
diff --git a/Source/Processors/RecordNode.h b/Source/Processors/RecordNode.h
index baadf10e0cb4acb6faae76b8355c7f86024c6409..ac44861133170b90cf7806f405a1319af4c039ce 100755
--- a/Source/Processors/RecordNode.h
+++ b/Source/Processors/RecordNode.h
@@ -102,14 +102,22 @@ public:
     */
     void createNewDirectory();
 
+    File getDataDirectory() {return rootFolder;}
+
     /** Signals when to create a new data directory when recording starts.*/
     bool newDirectoryNeeded;
 
+    bool isRecording;
+
+     /** Generate a Matlab-compatible datestring */
+    String generateDateString();
+
+
 private:
 
     /** Keep the RecordNode informed of acquisition and record states.
     */
-    bool isRecording, isProcessing, signalFilesShouldClose;
+    bool isProcessing, signalFilesShouldClose;
 
     /** User-selectable directory for saving data files. Currently
         defaults to the user's home directory.
@@ -165,9 +173,7 @@ private:
     /** Generates a default directory name, based on the current date and time */
     String generateDirectoryName();
 
-    /** Generate a Matlab-compatible datestring */
-    String generateDateString();
-
+   
     /** Generate filename for a given channel */
     void updateFileName(Channel* ch);
 
diff --git a/Source/Processors/SourceNode.cpp b/Source/Processors/SourceNode.cpp
index 67fa66afcf3f4cb1adb8115d1525d3a0d7cb5e73..5a8b53ccc8cd2f88e386c5b6ec1b6465b62bbc46 100755
--- a/Source/Processors/SourceNode.cpp
+++ b/Source/Processors/SourceNode.cpp
@@ -114,6 +114,7 @@ void SourceNode::updateSettings()
     {
 
         inputBuffer = dataThread->getBufferAddress();
+        dataThread->updateChannelNames();
         std::cout << "Input buffer address is " << inputBuffer << std::endl;
     }
 
@@ -125,6 +126,7 @@ void SourceNode::updateSettings()
         eventChannels.add(ch);
     }
 
+
 }
 
 void SourceNode::actionListenerCallback(const String& msg)
diff --git a/Source/Processors/SpikeDetector.cpp b/Source/Processors/SpikeDetector.cpp
index 1a5025421829e486c36f58e726e6d71872a5ec39..7ee4348b5d249bb15f5467c8f61004af599ea905 100755
--- a/Source/Processors/SpikeDetector.cpp
+++ b/Source/Processors/SpikeDetector.cpp
@@ -165,7 +165,7 @@ bool SpikeDetector::addElectrode(int nChans)
 
 float SpikeDetector::getDefaultThreshold()
 {
-    return 75.0f;
+    return 50.0f;
 }
 
 StringArray SpikeDetector::getElectrodeNames()
@@ -333,6 +333,8 @@ void SpikeDetector::addSpikeEvent(SpikeObject* s, MidiBuffer& eventBuffer, int p
 
     // std::cout << "Adding spike event for index " << peakIndex << std::endl;
 
+    s->eventType = SPIKE_EVENT_CODE;
+
     int numBytes = packSpike(s, spikeBuffer, 256);
 
     eventBuffer.addEvent(spikeBuffer, numBytes, peakIndex);
diff --git a/Source/Processors/SpikeDisplayNode.cpp b/Source/Processors/SpikeDisplayNode.cpp
index 161aed18f00c95c9393e388042bb8a21f9a4ac9e..ce983edeb85ae85672f1c696b2821bc06da9e97e 100755
--- a/Source/Processors/SpikeDisplayNode.cpp
+++ b/Source/Processors/SpikeDisplayNode.cpp
@@ -101,6 +101,28 @@ int SpikeDisplayNode::getNumberOfChannelsForElectrode(int elec)
     return 0;
 }
 
+String SpikeDisplayNode::getNameForElectrode(int elec)
+{
+
+    int electrodeIndex = -1;
+
+    for (int i = 0; i < eventChannels.size(); i++)
+    {
+        if (eventChannels[i]->eventType < 999)
+        {
+            electrodeIndex++;
+
+            if (electrodeIndex == elec)
+            {
+                std::cout << "Electrode " << elec << " has " << eventChannels[i]->eventType << " channels" << std::endl;
+                return eventChannels[i]->name;
+            }
+        }
+    }
+
+    return " ";
+}
+
 int SpikeDisplayNode::getNumElectrodes()
 {
     int nElectrodes = 0;
diff --git a/Source/Processors/SpikeDisplayNode.h b/Source/Processors/SpikeDisplayNode.h
index 66dcb85b44be709aece4b795320145063c9c961e..9de5055d33e4d141d33bb3d9abc418f807da3c88 100755
--- a/Source/Processors/SpikeDisplayNode.h
+++ b/Source/Processors/SpikeDisplayNode.h
@@ -71,7 +71,7 @@ public:
         return eventBuffer;
     }
 
-
+    String getNameForElectrode(int i);
     int getNumberOfChannelsForElectrode(int i);
     int getNumElectrodes();
 
diff --git a/Source/Processors/Visualization/LfpDisplayCanvas.cpp b/Source/Processors/Visualization/LfpDisplayCanvas.cpp
index 54f91aacb40c5805ad28173d2de4e950f4c31833..9a33de1c99100c0cf85a549c013df4c6ae0bc99e 100755
--- a/Source/Processors/Visualization/LfpDisplayCanvas.cpp
+++ b/Source/Processors/Visualization/LfpDisplayCanvas.cpp
@@ -183,6 +183,18 @@ void LfpDisplayCanvas::update()
 
     lfpDisplay->setNumChannels(nChans);
 
+    // update channel names
+	for (int i = 0; i < processor->getNumInputs(); i++)
+    {
+
+    	String chName = processor->channels[i]->getName();
+
+    	//std::cout << chName << std::endl;
+
+    	lfpDisplay->channelInfo[i]->setName(chName);
+
+    }
+
     lfpDisplay->setBounds(0,0,getWidth()-scrollBarThickness*2, lfpDisplay->getTotalHeight());
 
 }
@@ -807,6 +819,10 @@ LfpChannelDisplay::LfpChannelDisplay(LfpDisplayCanvas* c, LfpDisplay* d, int cha
     canvas(c), display(d), isSelected(false), chan(channelNumber), channelHeight(40), channelOverlap(300), range(1000.0f)
 {
 
+
+	name = String(channelNumber+1); // default is to make the channelNumber the name
+
+
     channelHeightFloat = (float) channelHeight;
 
     channelFont = Font("Default", channelHeight*0.6, Font::plain);
@@ -1002,6 +1018,11 @@ int LfpChannelDisplay::getChannelOverlap()
     return channelOverlap;
 }
 
+void LfpChannelDisplay::setName(String name_)
+{
+	name = name_;
+}
+
 // -------------------------------
 
 LfpChannelDisplayInfo::LfpChannelDisplayInfo(LfpDisplayCanvas* canvas_, LfpDisplay* display_, int ch)
@@ -1013,14 +1034,16 @@ LfpChannelDisplayInfo::LfpChannelDisplayInfo(LfpDisplayCanvas* canvas_, LfpDispl
 void LfpChannelDisplayInfo::paint(Graphics& g)
 {
 
+
+
     int center = getHeight()/2;
 
     g.setColour(lineColour);
 
     g.setFont(channelFont);
-    g.setFont(channelHeightFloat*0.6);
+    g.setFont(channelHeightFloat*0.3);
 
-    g.drawText(String(chan+1), 10, center-channelHeight/2, 200, channelHeight, Justification::left, false);
+    g.drawText(name, 10, center-channelHeight/2, 200, channelHeight, Justification::left, false);
 
 }
 
@@ -1087,4 +1110,4 @@ void eventDisplayInterface::paint(Graphics& g)
 
     //g.drawText(String(channelNumber), 8, 2, 200, 15, Justification::left, false);
 
-}
\ No newline at end of file
+}
diff --git a/Source/Processors/Visualization/LfpDisplayCanvas.h b/Source/Processors/Visualization/LfpDisplayCanvas.h
index 79f903e24154d02e0149ff69fb2e7c8c24f534b7..bbbf5bfbd429373b37dc771a0aff1c2e75c80d13 100755
--- a/Source/Processors/Visualization/LfpDisplayCanvas.h
+++ b/Source/Processors/Visualization/LfpDisplayCanvas.h
@@ -187,12 +187,17 @@ public:
     void setChannelHeight(int r);
     int getChannelHeight();
 
+
     bool setEventDisplayState(int ch, bool state);
     bool getEventDisplayState(int ch);
 
 
     Array<Colour> channelColours;
 
+    Array<LfpChannelDisplay*> channels;
+    Array<LfpChannelDisplayInfo*> channelInfo;
+
+
 private:
     int numChans;
 
@@ -206,6 +211,9 @@ private:
 
     bool eventDisplayEnabled[8];
 
+    Array<Colour> channelColours;
+
+
     float range;
 
 };
@@ -221,6 +229,8 @@ public:
     void select();
     void deselect();
 
+    void setName(String);
+
     void setColour(Colour c);
 
     void setChannelHeight(int);
@@ -243,6 +253,8 @@ protected:
 
     int chan;
 
+    String name;
+
     Font channelFont;
 
     Colour lineColour;
diff --git a/Source/Processors/Visualization/SpikeDisplayCanvas.cpp b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp
index fe16ddafc0a1c36265b1b66d4345aad9fbdd701a..cf904d76971b00497d37da260b8c413dfe337bcd 100755
--- a/Source/Processors/Visualization/SpikeDisplayCanvas.cpp
+++ b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp
@@ -20,8 +20,9 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 */
-
+ 
 #include "SpikeDisplayCanvas.h"
+#include "../RecordNode.h"
 
 SpikeDisplayCanvas::SpikeDisplayCanvas(SpikeDisplayNode* n) :
     processor(n), newSpike(false)
@@ -79,7 +80,8 @@ void SpikeDisplayCanvas::update()
 
     for (int i = 0; i < nPlots; i++)
     {
-        spikeDisplay->addSpikePlot(processor->getNumberOfChannelsForElectrode(i), i);
+        spikeDisplay->addSpikePlot(processor->getNumberOfChannelsForElectrode(i), i,
+                                   processor->getNameForElectrode(i));
     }
 
     spikeDisplay->resized();
@@ -117,6 +119,11 @@ void SpikeDisplayCanvas::refresh()
     repaint();
 }
 
+RecordNode* SpikeDisplayCanvas::getRecordNode()
+{
+    return processor->getProcessorGraph()->getRecordNode();
+}
+
 void SpikeDisplayCanvas::processSpikeEvents()
 {
 
@@ -214,12 +221,12 @@ void SpikeDisplay::removePlots()
         
 }
 
-void SpikeDisplay::addSpikePlot(int numChannels, int electrodeNum)
+void SpikeDisplay::addSpikePlot(int numChannels, int electrodeNum, String name_)
 {
 
     std::cout << "Adding new spike plot." << std::endl;
 
-    SpikePlot* spikePlot = new SpikePlot(canvas, electrodeNum, 1000 + numChannels);
+    SpikePlot* spikePlot = new SpikePlot(canvas, electrodeNum, 1000 + numChannels, name_);
     spikePlots.add(spikePlot);
     addAndMakeVisible(spikePlot);
 }
@@ -348,12 +355,14 @@ void SpikeDisplay::plotSpike(const SpikeObject& spike, int electrodeNum)
 
 // ----------------------------------------------------------------
 
-SpikePlot::SpikePlot(SpikeDisplayCanvas* sdc, int elecNum, int p) :
+SpikePlot::SpikePlot(SpikeDisplayCanvas* sdc, int elecNum, int p, String name_) :
      canvas(sdc), isSelected(false), electrodeNumber(elecNum),  plotType(p),
-    limitsChanged(true)
+    limitsChanged(true), name(name_), isRecording(false)
 
 {
 
+    recordNode = sdc->getRecordNode();
+
     font = Font("Default", 15, Font::plain);
 
     switch (p)
@@ -407,6 +416,9 @@ SpikePlot::SpikePlot(SpikeDisplayCanvas* sdc, int elecNum, int p) :
         rangeButtons.add(rangeButton);
     }
 
+    spikeBuffer = new uint8_t[MAX_SPIKE_BUFFER_LEN]; // MAX_SPIKE_BUFFER_LEN defined in SpikeObject.h
+
+
 }
 
 SpikePlot::~SpikePlot()
@@ -422,7 +434,7 @@ void SpikePlot::paint(Graphics& g)
 
     g.setFont(font);
 
-    g.drawText(String(electrodeNumber+1),10,0,50,20,Justification::left,false);
+    g.drawText(name,10,0,200,20,Justification::left,false);
 
 }
 
@@ -430,13 +442,139 @@ void SpikePlot::processSpikeObject(const SpikeObject& s)
 {
     //std::cout<<"ElectrodePlot::processSpikeObject()"<<std::endl;
 
+    // first, check if it's above threshold
+    bool aboveThreshold = false;
+
     for (int i = 0; i < nWaveAx; i++)
-        wAxes[i]->updateSpikeData(s);
+    {
+        aboveThreshold = aboveThreshold | wAxes[i]->checkThreshold(s);
+    }
+        
+    if (aboveThreshold)
+    {
+        for (int i = 0; i < nWaveAx; i++)
+            wAxes[i]->updateSpikeData(s);
+
+        for (int i = 0; i < nProjAx; i++)
+            pAxes[i]->updateSpikeData(s);
+    }
+    
+
+    // then record it!
+    if (recordNode->isRecording)
+    {
+        if (!isRecording)
+        {
+            // open file
+            openFile();
+
+            isRecording = true;
+            //std::cout << "Start recording spikes." << std::endl;
+       
+        }
+
+        if (aboveThreshold)
+        {
+             // write spike to disk
+            writeSpike(s);
+        }
+
+    } else {
+        
+        if (isRecording)
+        {
+            // close file
+            closeFile();
+
+            isRecording = false;
+            //std::cout << "Stop recording spikes." << std::endl;
+        }
+    }
 
-    for (int i = 0; i < nProjAx; i++)
-        pAxes[i]->updateSpikeData(s);
 }
 
+void SpikePlot::openFile()
+{
+    dataDirectory = recordNode->getDataDirectory();
+
+    filename = dataDirectory.getFullPathName();
+    filename += File::separator;
+    filename += name.removeCharacters(" ");
+    filename += ".spikes"; 
+
+    std::cout << "OPENING FILE: " << filename << std::endl;
+
+    File fileToUse = File(filename);
+
+    if (!fileToUse.exists())
+    {
+        // open it and write header
+        file = fopen(filename.toUTF8(), "ab");
+
+        String header = generateHeader();
+
+        fwrite(header.toUTF8(), 1, header.getNumBytesAsUTF8(), file);
+
+    } else {
+
+        // append it
+        file = fopen(filename.toUTF8(), "ab");
+    }
+
+
+}
+
+void SpikePlot::closeFile()
+{
+
+    std::cout << "CLOSING FILE: " << filename << std::endl;
+
+    if (file != NULL)
+    {
+        fclose(file);
+    }
+
+}
+
+void SpikePlot::writeSpike(const SpikeObject& s)
+{
+
+
+    packSpike(&s, spikeBuffer, 256);
+
+    fwrite(spikeBuffer, 1, 256, file);
+
+
+}
+
+String SpikePlot::generateHeader()
+{
+    String header = "header.format = 'OPEN EPHYS DATA FORMAT v0.0'; \n";
+
+    header += "header.header_bytes = ";
+    header += String(HEADER_SIZE);
+    header += ";\n";
+
+    header += "header.description = 'Spike data...live it up!'; \n";
+
+    header += "header.date_created = '";
+    header += recordNode->generateDateString();
+    header += "';\n";
+
+    header += "header.electrode = '";
+    header += name;
+    header += "';\n";
+
+    header += "header.channelType = 'Electrode';\n";
+
+    header = header.paddedRight(' ', HEADER_SIZE);
+
+    //std::cout << header << std::endl;
+
+    return header;
+}
+
+
 void SpikePlot::select()
 {
     isSelected = true;
@@ -611,7 +749,7 @@ void SpikePlot::clear()
 
 
 WaveAxes::WaveAxes(int channel) : GenericAxes(channel), drawGrid(true), 
-    bufferSize(10), spikeIndex(0), thresholdLevel(0.5f), range(250.0f),
+    bufferSize(10), spikeIndex(0), thresholdLevel(0.0f), range(250.0f),
     isOverThresholdSlider(false), isDraggingThresholdSlider(false)
 {
 
@@ -723,10 +861,11 @@ void WaveAxes::plotSpike(const SpikeObject& s, Graphics& g)
 void WaveAxes::drawThresholdSlider(Graphics& g)
 {
 
-    float h = getHeight()*thresholdLevel;
+    float h = getHeight()*(0.5f - thresholdLevel/range);
 
     g.setColour(thresholdColour);
     g.drawLine(0, h, getWidth(), h);
+    g.drawText(String(roundFloatToInt(thresholdLevel)),2,h,25,10,Justification::left, false);
 
 }
 
@@ -740,12 +879,15 @@ void WaveAxes::drawWaveformGrid(Graphics& g)
 
     for (float y = -range/2; y < range/2; y += 25.0f)
     {
-        g.drawLine(0,h/2 + y/range*h, w, h/2+ y/range*h);
+        if (y == 0)
+            g.drawLine(0,h/2 + y/range*h, w, h/2+ y/range*h,2.0f);
+        else
+            g.drawLine(0,h/2 + y/range*h, w, h/2+ y/range*h);
     }
    
 }
 
-void WaveAxes::updateSpikeData(const SpikeObject& s)
+bool WaveAxes::updateSpikeData(const SpikeObject& s)
 {
     if (!gotFirstSpike)
     {
@@ -754,12 +896,38 @@ void WaveAxes::updateSpikeData(const SpikeObject& s)
 
     SpikeObject newSpike = s;
 
-    spikeIndex++;
-    spikeIndex %= bufferSize;
+    //if (checkThreshold(newSpike))
+    //{
+        spikeIndex++;
+        spikeIndex %= bufferSize;
+
+        spikeBuffer.set(spikeIndex, newSpike); 
+    //    return true;
+
+   // } else {
+   //     return false;
+   // }
 
-    spikeBuffer.set(spikeIndex, newSpike);
 
     
+}
+
+bool WaveAxes::checkThreshold(const SpikeObject& s)
+{
+    int sampIdx = 40*type;
+
+     for (int i = 0; i < s.nSamples-1; i++)
+    {
+        
+        if (float(s.data[sampIdx]-32768)/float(*s.gain)*1000.0f > thresholdLevel)
+        {
+            return true;
+        }
+
+        sampIdx++;
+    }
+
+    return false;
 
 }
 
@@ -776,6 +944,8 @@ void WaveAxes::clear()
         
         spikeBuffer.add(so);
     }
+
+    repaint();
 }
 
 void WaveAxes::mouseMove(const MouseEvent& event)
@@ -785,7 +955,7 @@ void WaveAxes::mouseMove(const MouseEvent& event)
 
     float y = event.y;
 
-    float h = getHeight()*thresholdLevel;
+    float h = getHeight()*(0.5f - thresholdLevel/range);
 
    // std::cout << y << " " << h << std::endl;
 
@@ -827,7 +997,19 @@ void WaveAxes::mouseDrag(const MouseEvent& event)
 {
     if (isOverThresholdSlider)
     {
-        thresholdLevel = float(event.y) / float(getHeight());
+
+        float thresholdSliderPosition =  float(event.y) / float(getHeight());
+
+        if (thresholdSliderPosition > 0.5f)
+            thresholdSliderPosition = 0.5f;
+        else if (thresholdSliderPosition < 0.0f)
+            thresholdSliderPosition = 0.0f;
+
+
+        thresholdLevel = (0.5f - thresholdSliderPosition) * range;
+
+        //std::cout << "Threshold = " << thresholdLevel << std::endl;
+
         repaint();
     }
 }
@@ -886,7 +1068,7 @@ void ProjectionAxes::paint(Graphics& g)
                 0, imageDim-rangeY, rangeX, rangeY);
 }
 
-void ProjectionAxes::updateSpikeData(const SpikeObject& s)
+bool ProjectionAxes::updateSpikeData(const SpikeObject& s)
 {
     if (!gotFirstSpike)
     {
@@ -946,6 +1128,8 @@ void ProjectionAxes::clear()
 {
     projectionImage.clear(Rectangle<int>(0, 0, projectionImage.getWidth(), projectionImage.getHeight()),
                          Colours::black);
+
+    repaint();
 }
 
 void ProjectionAxes::n2ProjIdx(int proj, int* p1, int* p2)
@@ -1012,7 +1196,7 @@ GenericAxes::~GenericAxes()
 
 }
 
-void GenericAxes::updateSpikeData(const SpikeObject& newSpike)
+bool GenericAxes::updateSpikeData(const SpikeObject& newSpike)
 {
     if (!gotFirstSpike)
     {
diff --git a/Source/Processors/Visualization/SpikeDisplayCanvas.h b/Source/Processors/Visualization/SpikeDisplayCanvas.h
index 02ba77143ab868b2840866023d47934bbe1cdad6..ade7bd6c87f6e441a1e798be39209d796dc9488e 100755
--- a/Source/Processors/Visualization/SpikeDisplayCanvas.h
+++ b/Source/Processors/Visualization/SpikeDisplayCanvas.h
@@ -57,6 +57,7 @@ class GenericAxes;
 class ProjectionAxes;
 class WaveAxes;
 class SpikePlot;
+class RecordNode;
 
 /**
 
@@ -95,6 +96,8 @@ public:
 
     void buttonClicked(Button* button);
 
+    RecordNode* getRecordNode();
+
 private:
 
     SpikeDisplayNode* processor;
@@ -122,7 +125,7 @@ public:
 
     void removePlots();
     void clear();
-    void addSpikePlot(int numChannels, int electrodeNum);
+    void addSpikePlot(int numChannels, int electrodeNum, String name);
 
     void paint(Graphics& g);
 
@@ -161,12 +164,14 @@ private:
 
   Class for drawing the waveforms and projections of incoming spikes.
 
+  Also responsible for saving spikes.
+
 */
 
 class SpikePlot : public Component, Button::Listener
 {
 public:
-    SpikePlot(SpikeDisplayCanvas*, int elecNum, int plotType);
+    SpikePlot(SpikeDisplayCanvas*, int elecNum, int plotType, String name_);
     virtual ~SpikePlot();
 
     void paint(Graphics& g);
@@ -197,6 +202,8 @@ public:
 
 private:
 
+    bool isRecording;
+
 
     int plotType;
     int nWaveAx;
@@ -215,9 +222,22 @@ private:
     void setLimitsOnAxes();
     void updateAxesPositions();
 
+    String name;
 
     Font font;
 
+    // methods for recording:
+    void openFile();
+    void closeFile();
+    void writeSpike(const SpikeObject& s);
+    String generateHeader();
+
+    RecordNode* recordNode;
+    FILE* file;
+    String filename;
+    File dataDirectory;
+    uint8_t* spikeBuffer;
+
 };
 
 /**
@@ -236,7 +256,7 @@ public:
 
     virtual ~GenericAxes();
 
-    virtual void updateSpikeData(const SpikeObject& s);
+    virtual bool updateSpikeData(const SpikeObject& s);
 
     void setXLims(double xmin, double xmax);
     void getXLims(double* xmin, double* xmax);
@@ -280,7 +300,8 @@ public:
     WaveAxes(int channel);
     ~WaveAxes() {}
 
-    void updateSpikeData(const SpikeObject& s);
+    bool updateSpikeData(const SpikeObject& s);
+    bool checkThreshold(const SpikeObject& spike);
 
     void paint(Graphics& g);
 
@@ -312,6 +333,8 @@ private:
 
     void drawThresholdSlider(Graphics& g);
 
+    
+
     Font font;
 
     Array<SpikeObject> spikeBuffer;
@@ -344,7 +367,7 @@ public:
     ProjectionAxes(int projectionNum);
     ~ProjectionAxes() {}
 
-    void updateSpikeData(const SpikeObject& s);
+    bool updateSpikeData(const SpikeObject& s);
 
     void paint(Graphics& g);
 
diff --git a/Source/Processors/Visualization/SpikeObject.cpp b/Source/Processors/Visualization/SpikeObject.cpp
index c2665d123aca88f6505a8b9432228b22d30d8be2..bb7ce020b4f4ddc6ec1e19f0eb6db375f2c857d3 100755
--- a/Source/Processors/Visualization/SpikeObject.cpp
+++ b/Source/Processors/Visualization/SpikeObject.cpp
@@ -27,16 +27,13 @@
 #include "time.h"
 
 // Simple method for serializing a SpikeObject into a string of bytes
-int packSpike(SpikeObject* s, uint8_t* buffer, int bufferSize)
+int packSpike(const SpikeObject* s, uint8_t* buffer, int bufferSize)
 {
 
     //int reqBytes = 1 + 4 + 2 + 2 + 2 + 2 * s->nChannels * s->nSamples + 2 * s->nChannels * 2;
 
     int idx = 0;
 
-    s->eventType = SPIKE_EVENT_CODE;
-
-
     memcpy(buffer+idx, &(s->eventType), 1);
     idx += 1;
 
diff --git a/Source/Processors/Visualization/SpikeObject.h b/Source/Processors/Visualization/SpikeObject.h
index 1bd73f2ec990f3f2293f7808e7163191f97ff46e..5a71b9e5b9b8a74e553b7a926a15003b63e44fbb 100755
--- a/Source/Processors/Visualization/SpikeObject.h
+++ b/Source/Processors/Visualization/SpikeObject.h
@@ -68,7 +68,7 @@ struct SpikeObject
 };
 
 /** Simple method for serializing a SpikeObject into a string of bytes, returns true is the packaged spike buffer is valid */
-int packSpike(SpikeObject* s, uint8_t* buffer, int bufferLength);
+int packSpike(const SpikeObject* s, uint8_t* buffer, int bufferLength);
 
 /** Simple method for deserializing a string of bytes into a Spike object, returns true is the provided spike buffer is valid */
 bool unpackSpike(SpikeObject* s, const uint8_t* buffer, int bufferLength);
diff --git a/Source/Processors/Visualization/Visualizer.h b/Source/Processors/Visualization/Visualizer.h
index 3825800a64294b488ba5f5d289bc5bf99ad8130d..0e23f3d2cfcb3af037fc5a808728ac1f2b5018b7 100755
--- a/Source/Processors/Visualization/Visualizer.h
+++ b/Source/Processors/Visualization/Visualizer.h
@@ -94,8 +94,6 @@ public:
     /** Loads parameters from XML */
     virtual void loadVisualizerParameters(XmlElement* xml) { }
 
-
-
 };
 
 
diff --git a/Source/UI/ProcessorList.cpp b/Source/UI/ProcessorList.cpp
index d5998e9343ea85e7c93a92d3cd3b74f6b1e5e51f..4cf9a433c7d5988ab5c2f0088e535898ae24c752 100755
--- a/Source/UI/ProcessorList.cpp
+++ b/Source/UI/ProcessorList.cpp
@@ -78,7 +78,8 @@ ProcessorList::ProcessorList()
     filters->addSubItem(new ProcessorListItem("Spike Detector"));
     //filters->addSubItem(new ProcessorListItem("Resampler"));
     filters->addSubItem(new ProcessorListItem("Phase Detector"));
-    filters->addSubItem(new ProcessorListItem("Digital Ref"));
+    //filters->addSubItem(new ProcessorListItem("Digital Ref"));
+    filters->addSubItem(new ProcessorListItem("Channel Map"));
 
     ProcessorListItem* sinks = new ProcessorListItem("Sinks");
     sinks->addSubItem(new ProcessorListItem("LFP Viewer"));
diff --git a/Source/UI/UIComponent.cpp b/Source/UI/UIComponent.cpp
index 7d94fb6b2ea432e14860752e4831db6a34401eb8..f9de7eb391bfbc72533158217fd0e90b94fccbdd 100755
--- a/Source/UI/UIComponent.cpp
+++ b/Source/UI/UIComponent.cpp
@@ -92,7 +92,7 @@ UIComponent::UIComponent(MainWindow* mainWindow_, ProcessorGraph* pgraph, AudioC
     mainWindow->setMenuBar(this);
 #endif
 
-   // getEditorViewport()->loadState(File("/home/jsiegle/Programming/GUI/Builds/Linux/build/rhythm_config.xml"));
+    //getEditorViewport()->loadState(File("/home/jsiegle/Programming/GUI/Builds/Linux/build/spike_display_2.xml"));
 
 }