scripts/channelClasses/standard/CzRef.java
/////////////////////////////////////////////////////////////////
// Processes data by rereferencing EEG channels to Cz
//
// This code is compiled at runtime, but compilation can be tested by:
// javac -cp build scripts/channelClasses/standard/CzRef.java
// rm scripts/channelClasses/standard/CzRef.class
/////////////////////////////////////////////////////////////////
package standard;
import java.io.*;
import java.util.*;
import generalClasses.*;
import recordingClasses.Recording;
import seriesClasses.*;
import channelClasses.ChannelScript;
import static channelClasses.Channel.*;
/////////////////////////////////////////////////////////////////
/** Processes data by rereferencing EEG channels to Cz. <b>It
* (probably) should only be applied to common-ref data, and
* probably should only be called if Cz is known not be noisy.</b>
*
* <p>NB 1. This algorithm simply subtracts Cz|A1A2 from all
* EEG waveforms. <b>As such, it makes clearest sense when all EEG
* channels have A1A2 as their common reference.</b> If they all have
* some other reference, but still common, then this script should be
* edited accordingly.
* <p>NB 2. Subtracting the average only makes sense if
* artifact-affected channels are excluded beforehand.
* This can be ensured by only ever calling this option <i>subsequent
* to</i> one that performs channel rejection, e.g.<pre>
* -scriptChannel Standard:CzRef
* </pre>
* so that if Cz is rejected, this script will fail (as it should).
*
* <p>The effect of referencing can be seen be comparing the result
* of <pre>
* java -cp build:lib/derby.jar frontendClasses/CLI -fn data/81237443-1.EC.NS5 -scriptChannel Standard:CzRef -paradigm ec -scriptEpoch OneLong -chanSelection "Mode='EEG'" -reviewSeries
* </pre>
* with and without ':CzRef' in the command line.
*/
public class CzRef extends ChannelScript
{
/** Recording instance to be operated on */
Recording rec = null;
/** Log of warnings generated during update */
ArrayList<String> warnings = new ArrayList<String>();
////////////////////////////////////////////////////////////////////
/** Initialize instance by setting its parameters to default values.
*/
public CzRef(Recording rec) {
this.rec = rec;
} // CzRef
////////////////////////////////////////////////////////////////////
/** Update recording data by performing channel-oriented operations.
* <p>Available modes are EEG, EOG, REF, EMG, EDA, RES, ECG, EVE.
*/
public void update() {
// Partition results into ref, EEG and non-EEG channels
SiteSet refSite = new SiteSet(new Site("Cz"),new Site("A1A2"));
ArrayList<SeriesAnalog> refs = selectSite(rec, refSite);
ArrayList<SeriesAnalog> result = selectMode(rec, DataMode.EEG);
ArrayList<SeriesAnalog> rest = discardMode(rec, DataMode.EEG);
// Check that the reference channel is unambiguous
if(refs.size()==0) {
warnings.add("Script failure in CzRef: can't find 'Cz|A1A2'");
return;
}
if(refs.size()>1) {
warnings.add("Script failure in CzRef: found multiple 'Cz|A1A2'");
return;
}
SeriesAnalog ref = refs.get(0).clone();// This is new reference channel
// Ideally, check that all EEG channels have a common reference,
// and, if not, create a warning or error.
// Rereference the EEG, and merge with non-EEG channels
for(SeriesAnalog c: result)
c.sub(ref);
result = listsUnion(result, rest);
// Update Recording object
replaceAllSeries(rec, result);
} // update
////////////////////////////////////////////////////////////////////
/** Dump summary of this class or object
* @return String representation of this object
*/
public String toString() {
String s = "<<<"+this.getClass().toString()+">>>\n";
s += "References EEG channels by subtracting Cz\n";
for(String w: warnings)
s += w+"\n";
return s;
} // toString
}