Ejemplo n.º 1
0
        public MainWindow()
        {
            bool r;
            do //first get HDR file and open BDF file
            {
                OpenFileDialog dlg = new OpenFileDialog();
                dlg.Title = "Open Header of dataset to be edited...";
                dlg.DefaultExt = ".hdr"; // Default file extension
                dlg.Filter = "HDR Files (.hdr)|*.hdr"; // Filter files by extension
                Nullable<bool> result = dlg.ShowDialog();
                if (result == null || result == false) Environment.Exit(0); 

                directory = System.IO.Path.GetDirectoryName(dlg.FileName); //will use to find other files in dataset
                headerFileName = System.IO.Path.GetFileNameWithoutExtension(dlg.FileName);

                header = (new HeaderFileReader(dlg.OpenFile())).read();
                updateFlag = header.Events.ContainsKey("**ArtifactBegin"); //indicates that we are editing a dataset that has already been edited for artifacts

                bdf = new BDFEDFFileReader(new FileStream(System.IO.Path.Combine(directory, header.BDFFile),
                        FileMode.Open, FileAccess.Read));

                //make list of candidate EEG channels, so that channel selection window can use it
                BDFLength = (double)bdf.NumberOfRecords * bdf.RecordDuration;
                string trans = bdf.transducer(0); //here we assumne that channel 0 is an EEG channel
                for (int i = 0; i < bdf.NumberOfChannels - 1; i++) //exclude Status channel
                    if (bdf.transducer(i) == trans) EEGChannels.Add(i);

                Window1 w = new Window1(this); //open channel selection and file approval window
                r = (bool)w.ShowDialog();

            } while (r == false);

            InitializeComponent();

            Log.writeToLog("Starting EEGArtifactEditor " + Assembly.GetExecutingAssembly().GetName().Version.ToString() +
                " on dataset " + headerFileName);
            ViewerGrid.Width = BDFLength;

            try
            {
                //process Events in current dataset; we have to do this now in case this is an update situation, but don't have to when we finish
                Event.EventFactory.Instance(header.Events); // set up the factory, based on this Event dictionary
                //and read them in
                EventFileReader efr = new EventFileReader(
                    new FileStream(System.IO.Path.Combine(directory, header.EventFile),
                        FileMode.Open, FileAccess.Read)); // open Event file

                foreach (InputEvent ie in efr)// read in all Events into list
                    events.Add(new OutputEvent(ie));
                efr.Close(); //now events is list of Events in the dataset

                //now set zeroTime for this BDF file, after finding an appropriate (non-"naked") Event
                bool ok = false;
                foreach (OutputEvent ev in events)
                    if (header.Events[ev.Name].IsCovered)
                    {
                        bdf.setZeroTime(ev);
                        ok = true;
                        break;
                    }
                if (!ok)
                {
                    ErrorWindow ew = new ErrorWindow();
                    ew.Message = "Unable to find a covered Event in this dataset on which to synchronize clocks. Exiting.";
                    ew.ShowDialog();
                    Log.writeToLog("Unable to synchronize clocks.");
                    this.Close();
                }

                if (updateFlag) //re-editing this dataset for artifacts
                {
                    Event.EventFactory.Instance(header.Events); // set up the factory, based on this Event dictionary
                    //and read them in
                    OutputEvent ev;
                    int i = 0;
                    double left;
                    while (i < events.Count)
                    {
                        ev = events[i];
                        if (ev.Name == "**ArtifactBegin")
                        {
                            left = bdf.timeFromBeginningOfFileTo(ev);
                            events.Remove(ev);
                            while (i < events.Count)
                            {
                                ev = events[i];
                                if (ev.Name == "**ArtifactEnd")
                                {
                                    MarkerCanvas.createMarkRegion(left, bdf.timeFromBeginningOfFileTo(ev));
                                    events.Remove(ev);
                                    break;
                                }
                                if (ev.Name == "**ArtifactBegin")
                                    throw (new Exception("Unmatched artifact Event in Event file " +
                                        System.IO.Path.Combine(directory, header.EventFile)));
                                i++;
                            }
                        }
                        else
                            i++;
                    }
                }

                //initialize the individual channel canvases

                foreach (int chan in selectedEEGChannels)
                {
                    ChannelCanvas cc = new ChannelCanvas(this, chan);
                    currentChannelList.Add(cc);
                    ViewerCanvas.Children.Add(cc);
                    ViewerCanvas.Children.Add(cc.offScaleRegions);
                }


                Title = headerFileName; //set window title
                BDFFileInfo.Content = bdf.ToString();
                HDRFileInfo.Content = header.ToString();

                ElectrodeInputFileStream eif = new ElectrodeInputFileStream(
                    new FileStream(System.IO.Path.Combine(directory, header.ElectrodeFile),
                        FileMode.Open, FileAccess.Read)); //open Electrode file
                electrodes = eif.etrPositions;

                //initialize vertical gridline array; never more than 18
                for (int i = 0; i < 18; i++)
                {
                    Line l = new Line();
                    Grid.SetRow(l, 0);
                    Grid.SetColumn(l, 0);
                    l.Y1 = 0D;
                    l.HorizontalAlignment = HorizontalAlignment.Left;
                    l.VerticalAlignment = VerticalAlignment.Stretch;
                    l.IsHitTestVisible = false;
                    l.Stroke = Brushes.LightBlue;
                    l.Visibility = Visibility.Hidden;
                    Panel.SetZIndex(l, int.MaxValue);
                    VerticalGrid.Children.Add(l);
                    gridlines[i] = l;
                }

                //Initialize timer
                timer.AutoReset = true;
                timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);

                //Initialize channel information popup
                Color c1 = Color.FromArgb(0xFF, 0xF8, 0xF8, 0xF8);
                Color c2 = Color.FromArgb(0xFF, 0xC8, 0xC8, 0xC8);
                popupTB.Background = new LinearGradientBrush(c1, c2, 45D);
                popupTB.Foreground = Brushes.Black;
                popupTB.Padding = new Thickness(4D);
                Border b = new Border();
                b.BorderThickness = new Thickness(1);
                b.CornerRadius = new CornerRadius(4);
                b.BorderBrush = Brushes.Tomato;
                b.Margin = new Thickness(0, 0, 24, 24); //allows drop shadow to show up
                b.Effect = new DropShadowEffect();
                b.Child = popupTB;
                channelPopup.Placement = PlacementMode.MousePoint;
                channelPopup.AllowsTransparency = true;
                channelPopup.Child = b;

                //Initialize FOV slider
                FOV.Maximum = Math.Log10(BDFLength);
                FOV.Value = 1D;
                FOVMax.Text = BDFLength.ToString("0");

                //Note file always uses the "main" orginal dataset name, which should be the BDFFile name; this keeps notes from all levels of
                //processing in the same place
                noteFilePath = System.IO.Path.Combine(directory, System.IO.Path.GetFileNameWithoutExtension(header.BDFFile) + ".notes.txt");
            }
            catch (Exception ex)
            {
                ErrorWindow ew = new ErrorWindow();
                ew.Message = "Error in EEGArtifactEditor initialization" + ex.Message;
                ew.ShowDialog();
                this.Close(); //exit
            }

            //from here on the program is GUI-event driven
        }
Ejemplo n.º 2
0
        public Header.Header read()
        {
            Header.Header header = new Header.Header();
            try
            {
                xr.ReadStartElement("ExperimentDescription", nameSpace);
                xr.ReadStartElement("SoftwareVersion", nameSpace);
                header.SoftwareVersion = xr.ReadContentAsString();
                xr.ReadEndElement(/* SoftwareVersion */);
                xr.ReadStartElement("Title", nameSpace);
                header.Title = xr.ReadContentAsString();
                xr.ReadEndElement(/* Title */);
                xr.ReadStartElement("LongDescription", nameSpace);
                header.LongDescription = xr.ReadContentAsString();
                xr.ReadEndElement(/* LongDescription */);

                header.Experimenter = new List<string>();
                while (xr.Name == "Experimenter")
                {
                    xr.ReadStartElement(/* Experimenter */);
                    header.Experimenter.Add(xr.ReadContentAsString());
                    xr.ReadEndElement(/* Experimenter */);
                }
                xr.ReadStartElement("Status", nameSpace);
                header.Status = xr.ReadContentAsInt();
                xr.ReadEndElement(/* Status */);

                if (xr.Name == "Other")
                {
                    header.OtherExperimentInfo = new Dictionary<string, string>();
                    do
                    {
                        string name = xr["Name"];
                        xr.ReadStartElement(/* Other */);
                        string value = xr.ReadContentAsString();
                        header.OtherExperimentInfo.Add(name, value);
                        xr.ReadEndElement(/* Other */);
                    } while (xr.Name == "Other");
                }

                if (xr.Name == "GroupVar")
                {
                    header.GroupVars = new GroupVarDictionary.GroupVarDictionary();
                    do {
                        xr.ReadStartElement(/* GroupVar */);
                        GroupVarDictionary.GVEntry gve = new GVEntry();
                        xr.ReadStartElement("Name", nameSpace);
                        string name = xr.ReadContentAsString();
                        if (name.Length > 24)
                            throw new Exception("name too long for GV " + name);
                        xr.ReadEndElement(/* Name */);
                        xr.ReadStartElement("Description", nameSpace);
                        gve.Description = xr.ReadContentAsString();
                        xr.ReadEndElement(/* Description */);
                        if (xr.Name == "GV")
                        {
                            gve.GVValueDictionary = new Dictionary<string, int>();
                            do
                            {
                                string key = xr["Desc", nameSpace];
                                xr.ReadStartElement(/* GV */);
                                int val = xr.ReadContentAsInt();
                                if (val > 0)
                                    gve.GVValueDictionary.Add(key, val);
                                else
                                    throw new Exception("invalid value for GV "+ name);
                                xr.ReadEndElement(/* GV */);
                            }
                            while (xr.Name == "GV");
                        }
                        header.GroupVars.Add(name, gve);
                        xr.ReadEndElement(/* GroupVar */);
                    } while (xr.Name == "GroupVar");
                }

                if (xr.Name == "Event")
                {
                    header.Events = new EventDictionary.EventDictionary(header.Status);
                    do {
                        EventDictionaryEntry ede = new EventDictionaryEntry();
                        if (xr.MoveToAttribute("Type"))
                        {
                            string s = xr.ReadContentAsString();
                            if (s == "*")
                                ede.intrinsic = null;
                            else
                                ede.intrinsic = s != "extrinsic";
                        } //else Type is intrinsic by default
                        if (xr.MoveToAttribute("Clock")) //is there a Clock attribute?
                        {
                            string s = xr.ReadContentAsString();
                            if (s == "Absolute")
                                ede.BDFBased = false;
                            else if (s == "BDF-based")
                            {
                                if (ede.IsCovered) throw new Exception("Incompatible Type and Clock attributes in Event");
                                ede.BDFBased = true;
                            }
                            else throw new Exception("Invalid Clock attribute in Event");
                        } //else clock is Absolute by default
                        xr.ReadStartElement(/* Event */);
                        xr.ReadStartElement("Name", nameSpace);
                        string name = xr.ReadContentAsString();
                        xr.ReadEndElement(/* Event */);
                        xr.ReadStartElement("Description", nameSpace);
                        ede.Description = xr.ReadContentAsString();
                        xr.ReadEndElement(/* Description */);
                        if (ede.IsCovered && !(bool)ede.intrinsic)
                        {
                            xr.ReadStartElement("Channel", nameSpace);
                            ede.channelName = xr.ReadContentAsString();
                            xr.ReadEndElement(/* Channel */);
                            xr.ReadStartElement("Edge", nameSpace);
                            ede.rise = xr.ReadContentAsString() == "rising";
                            xr.ReadEndElement(/* Edge */);
                            ede.location = (xr.Name == "Location" ? (xr.ReadElementContentAsString() == "after") : false); //leads by default
                            ede.channelMax = xr.Name == "Max" ? xr.ReadElementContentAsDouble() : 0D; //zero by default
                            ede.channelMin = xr.Name == "Min" ? xr.ReadElementContentAsDouble() : 0D; //zero by default
                            if (ede.channelMax < ede.channelMin)
                                throw new Exception("invalid max/min signal values in extrinsic Event " + name);
                            //Note: Max and Min are optional; if neither is specified, 0.0 will always be used as threshold
                        }
                        if (xr.Name == "Ancillary")
                        {
                            xr.ReadStartElement(/* Ancillary */);
                            ede.ancillarySize = xr.ReadContentAsInt();
                            xr.ReadEndElement(/* Ancillary */);
                        }
                        if (xr.Name == "GroupVar")
                        {
                            ede.GroupVars = new List<GVEntry>();
                            do {
                                string gvName = xr["Name", nameSpace];
                                bool isEmpty = xr.IsEmptyElement;
                                xr.ReadStartElement(/* GroupVar */);
                                GVEntry gve;
                                if (header.GroupVars.TryGetValue(gvName, out gve))
                                    ede.GroupVars.Add(gve);
                                else throw new Exception("invalid GroupVar " + gvName + " in Event " + name);
                                if(!isEmpty) xr.ReadEndElement(/* GroupVar */);
                            } while (xr.Name == "GroupVar");
                        }
                        header.Events.Add(name, ede);
                        xr.ReadEndElement(/* Event */);
                    } while (xr.Name == "Event");
                }
                xr.ReadEndElement(/* ExperimentDescription */);
                xr.ReadStartElement("SessionDescription", nameSpace);
                xr.ReadStartElement("Date", nameSpace);
                header.Date = xr.ReadContentAsString();
                xr.ReadEndElement(/* Date */);
                xr.ReadStartElement("Time", nameSpace);
                header.Time = xr.ReadContentAsString();
                xr.ReadEndElement(/* Time */);
                xr.ReadStartElement("Subject", nameSpace);
                header.Subject = xr.ReadContentAsInt();
                xr.ReadEndElement(/* Subject */);
                if (xr.Name == "Agent")
                {
                    xr.ReadStartElement(/* Agent */);
                    header.Agent = xr.ReadContentAsInt();
                    xr.ReadEndElement(/* Agent */);
                }
                header.Technician = new List<string>();
                while (xr.Name == "Technician")
                {
                    xr.ReadStartElement(/* Technician */);
                    header.Technician.Add(xr.ReadContentAsString());
                    xr.ReadEndElement(/* Technician */);
                }
                if (xr.Name == "Other") {
                    header.OtherSessionInfo = new Dictionary<string, string>();
                    do
                    {
                        string name = xr["Name"];
                        xr.ReadStartElement(/* Other */);
                        string value = xr.ReadContentAsString();
                        xr.ReadEndElement(/* Other */);
                        header.OtherSessionInfo.Add(name, value);
                    } while (xr.Name == "Other");
                }
                xr.ReadStartElement("BDFFile", nameSpace);
                header.BDFFile = xr.ReadContentAsString();
                xr.ReadEndElement(/* BDFFile */);
                xr.ReadStartElement("EventFile", nameSpace);
                header.EventFile = xr.ReadContentAsString();
                xr.ReadEndElement(/* EventFile */);
                xr.ReadStartElement("ElectrodeFile", nameSpace);
                header.ElectrodeFile = xr.ReadContentAsString();
                xr.ReadEndElement(/* ElectrodeFile */);
                if (xr.Name == "Comment")
                {
                    xr.ReadStartElement(/* Comment */);
                    header.Comment = xr.ReadContentAsString(); //Optional comment
                    xr.ReadEndElement(/* Comment */);
                }
                xr.ReadEndElement(/* SessionDescription */);
                return header;
            }
            catch (Exception e)
            {
                XmlNodeType nodeType = xr.NodeType;
                string name = xr.Name;
                throw new Exception("HeaderFileReader.read: Error processing " + nodeType.ToString() +
                    " named " + name + ": " + e.Message);
            }
        }
Ejemplo n.º 3
0
        public MainWindow()
        {
            Log.writeToLog("Starting DatasetReviewer " + Assembly.GetExecutingAssembly().GetName().Version.ToString());

            do
            {
                bool r;
                do
                {
                    System.Windows.Forms.OpenFileDialog dlg = new System.Windows.Forms.OpenFileDialog();
                    dlg.Title = "Open Header file to be displayed...";
                    dlg.DefaultExt = ".hdr"; // Default file extension
                    dlg.Filter = "HDR Files (.hdr)|*.hdr"; // Filter files by extension
                    bool result = dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK;
                    if (!result) Environment.Exit(0);

                    directory = System.IO.Path.GetDirectoryName(dlg.FileName); //will use to find other files in dataset
                    headerFileName = System.IO.Path.GetFileNameWithoutExtension(dlg.FileName);
                    try
                    {
                        head = (new HeaderFileReader(dlg.OpenFile())).read();
                    }
                    catch (Exception e)
                    {
                        r = false; //loop around again
                        ErrorWindow ew = new ErrorWindow();
                        ew.Message = "Error reading Header file: " + e.Message;
                        continue;
                    }
                    ED = head.Events;

                    try
                    {
                        bdf = new BDFEDFFileStream.BDFEDFFileReader(
                            new FileStream(System.IO.Path.Combine(directory, head.BDFFile),
                                FileMode.Open, FileAccess.Read));
                    }
                    catch (Exception e)
                    {
                        r = false; //loop around again
                        ErrorWindow ew = new ErrorWindow();
                        ew.Message = "Error reading BDF file header: " + e.Message;
                        ew.ShowDialog();
                        continue;
                    }
                    BDFLength = (double)bdf.NumberOfRecords * bdf.RecordDurationDouble;

                    Window1 w = new Window1(this);
                    r = (bool)w.ShowDialog();

                } while (r == false);

                Log.writeToLog("     on dataset " + headerFileName);

                if (includeANAs)
                {
                    foreach (EventDictionaryEntry ede in ED.Values) // add ANA channels that are referenced by extrinsic Events
                    {
                        if (ede.IsCovered && ede.IsExtrinsic)
                        {
                            int chan = bdf.ChannelNumberFromLabel(ede.channelName);
                            if (!channelList.Contains(chan)) //don't enter duplicate
                                channelList.Add(chan);
                        }
                    }
                }
            } while (channelList.Count == 0);

            InitializeComponent();

            //initialize the individual channel graphs
            foreach (int i in channelList)
            {
                ChannelGraph pg = new ChannelGraph(this, i);
                GraphCanvas.Children.Add(pg);
            }

            Title = headerFileName; //set window title
            BDFFileInfo.Content = bdf.ToString();
            HDRFileInfo.Content = head.ToString();
            Event.EventFactory.Instance(head.Events); // set up the factory
            EventFileReader efr = null;
            try
            {
                    efr = new EventFileReader(
                        new FileStream(System.IO.Path.Combine(directory, head.EventFile),
                            FileMode.Open, FileAccess.Read)); // open Event file
                bool z = false;
                foreach (Event.InputEvent ie in efr)// read in all Events into dictionary
                {
                    if (ie.IsNaked)
                        events.Add(ie);
                    else if (events.Count(e => e.GC == ie.GC) == 0) //quietly skip duplicates
                    {
                        if (!z) //use first found covered Event to synchronize clocks
                            z = bdf.setZeroTime(ie);
                        events.Add(ie);
                    }
                }
                efr.Close(); //now events is Dictionary of Events in the dataset; lookup by GC
            }
            catch (Exception e)
            {
                ErrorWindow ew = new ErrorWindow();
                ew.Message = "Error reading Event file : " + e.Message + ". Exiting DatasetReviewer.";
                ew.ShowDialog();
                Log.writeToLog(Environment.NewLine +  e.StackTrace);
                Environment.Exit(0);
            }

            try
            {
                ElectrodeInputFileStream eif = new ElectrodeInputFileStream(
                    new FileStream(System.IO.Path.Combine(directory, head.ElectrodeFile),
                        FileMode.Open, FileAccess.Read)); //open Electrode file
                electrodes = eif.etrPositions; //read 'em in
            }
            catch (Exception e)
            {
                ErrorWindow ew = new ErrorWindow();
                ew.Message = "Error reading Electrode file : " + e.Message + ". Exitting DatasetReviewer.";
                ew.ShowDialog();
                Log.writeToLog(Environment.NewLine + e.StackTrace);
                Environment.Exit(0);
            }

            EventMarkers.Width = BDFLength;
            eventTB = new TextBlock(new Run("Events"));
            Canvas.SetBottom(eventTB, ScrollBarSize + 13D);

            //initialize gridline array
            for (int i = 0; i < 18; i++)
            {
                Line l = new Line();
                Grid.SetRow(l, 0);
                Grid.SetColumn(l, 0);
                Grid.SetColumnSpan(l, 2);
                l.Y1 = 0D;
                l.HorizontalAlignment = HorizontalAlignment.Left;
                l.VerticalAlignment = VerticalAlignment.Stretch;
                l.IsHitTestVisible = false;
                l.Stroke = Brushes.LightBlue;
                l.Visibility = Visibility.Hidden;
                Panel.SetZIndex(l, int.MinValue);
                MainFrame.Children.Add(l);
                gridlines[i] = l;
            }

            //Initialize timer
            timer.AutoReset = true;
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);

            //Initialize channel information popup
            Color c1 = Color.FromArgb(0xFF, 0xF8, 0xF8, 0xF8);
            Color c2 = Color.FromArgb(0xFF, 0xC8, 0xC8, 0xC8);
            popupTB.Background = new LinearGradientBrush(c1, c2, 45D);
            popupTB.Foreground = Brushes.Black;
            popupTB.Padding = new Thickness(4D);
            Border b = new Border();
            b.BorderThickness = new Thickness(1);
            b.CornerRadius = new CornerRadius(4);
            b.BorderBrush = Brushes.Tomato;
            b.Margin = new Thickness(0, 0, 24, 24); //allows drop shadow to show up
            b.Effect = new DropShadowEffect();
            b.Child = popupTB;
            channelPopup.Placement = PlacementMode.MousePoint;
            channelPopup.AllowsTransparency = true;
            channelPopup.Child = b;

            //Initialize Event information popup
            eventPopupTB.Background = new LinearGradientBrush(c1, c2, 45D);
            eventPopupTB.Foreground = Brushes.Black;
            eventPopupTB.Padding = new Thickness(4D);
            b = new Border();
            b.BorderThickness = new Thickness(1);
            b.CornerRadius = new CornerRadius(4);
            b.BorderBrush = Brushes.Tomato;
            b.Margin = new Thickness(0, 0, 24, 24); //allows drop shadow to show up
            b.Effect = new DropShadowEffect();
            b.Child = eventPopupTB;
            eventPopup.Placement = PlacementMode.MousePoint;
            eventPopup.AllowsTransparency = true;
            eventPopup.Child = b;

            //Initialize FOV slider
            FOV.Maximum = Math.Log10(BDFLength);
            FOV.Value = 1D;
            FOVMax.Text = BDFLength.ToString("0");

            //Initialize Event selector
            bool first = true;
            foreach (EventDictionaryEntry e in head.Events.Values)
            {
                MenuItem mi = (MenuItem)EventSelector.FindResource("EventMenuItem");
                mi.Header = e.Name;
                if (first)
                {
                    mi.IsChecked = true;
                    first = false;
                }
                EventSelector.Items.Add(mi);
            }

            noteFilePath = System.IO.Path.Combine(directory,System.IO.Path.ChangeExtension(head.BDFFile,".notes.txt"));
            //from here on the program is GUI-event driven
        }
Ejemplo n.º 4
0
 public HeaderFileWriter(Stream str, Header.Header head)
 {
     try
     {
         if (str == null) return;
         if (!str.CanWrite) throw new IOException("unable to write to stream");
         XmlWriterSettings settings = new XmlWriterSettings();
         settings.Indent = true;
         settings.CloseOutput = true;
         settings.Encoding = Encoding.UTF8;
         settings.CheckCharacters = true;
         xw = XmlWriter.Create(str, settings);
         xw.WriteStartDocument();
         xw.WriteStartElement("Header");
         xw.WriteStartElement("ExperimentDescription");
         xw.WriteElementString("SoftwareVersion", head.SoftwareVersion);
         xw.WriteElementString("Title", head.Title);
         xw.WriteElementString("LongDescription", head.LongDescription);
         foreach (string s in head.Experimenter)
             xw.WriteElementString("Experimenter", s);
         xw.WriteElementString("Status", head.Status.ToString("0"));
         if (head.OtherExperimentInfo != null)
             foreach (KeyValuePair<string, string> other in head.OtherExperimentInfo)
             {
                 xw.WriteStartElement("Other");
                 xw.WriteAttributeString("Name", other.Key);
                 xw.WriteString(other.Value);
                 xw.WriteEndElement(/* Other */);
             }
         foreach (GroupVarDictionary.GVEntry gve in head.GroupVars.Values)
         {
             xw.WriteStartElement("GroupVar");
             xw.WriteElementString("Name", gve.Name);
             xw.WriteElementString("Description", gve.Description);
             if(gve.GVValueDictionary != null) // will be null if integer values just stand for themselves
                 foreach (KeyValuePair<string, int> i in gve.GVValueDictionary)
                 {
                     xw.WriteStartElement("GV");
                     xw.WriteAttributeString("Desc", i.Key);
                     xw.WriteString(i.Value.ToString("0"));
                     xw.WriteEndElement(/* GV */);
                 }
             xw.WriteEndElement(/* GroupVar */);
         }
         foreach (KeyValuePair<string, EventDictionaryEntry> ede in head.Events)
         {
             xw.WriteStartElement("Event");
             xw.WriteAttributeString("Type", ede.Value.IsCovered ? (bool)ede.Value.intrinsic ? "intrinsic" : "extrinsic" : "*");
             xw.WriteAttributeString("Clock", ede.Value.BDFBased ? "BDF-based" : "Absolute");
             xw.WriteElementString("Name", ede.Key);
             xw.WriteElementString("Description", ede.Value.Description);
             if (ede.Value.IsCovered && !(bool)ede.Value.intrinsic)
             {
                 xw.WriteElementString("Channel", ede.Value.channelName);
                 xw.WriteElementString("Edge", ede.Value.rise ? "rising" : "falling");
                 xw.WriteElementString("Location", ede.Value.location ? "after" : "before");
                 if (ede.Value.channelMax != 0)
                     xw.WriteElementString("Max", ede.Value.channelMax.ToString("G"));
                 if (ede.Value.channelMin != 0)
                     xw.WriteElementString("Min", ede.Value.channelMin.ToString("G"));
             }
             if (ede.Value.ancillarySize != 0)
                 xw.WriteElementString("Ancillary", ede.Value.ancillarySize.ToString("0"));
             if(ede.Value.GroupVars!=null)
                 foreach (GVEntry gv in ede.Value.GroupVars)
                 {
                     xw.WriteStartElement("GroupVar", "");
                     xw.WriteAttributeString("Name", gv.Name);
                     xw.WriteEndElement(/* GroupVar */);
                 }
             xw.WriteEndElement(/* Event */);
         }
         xw.WriteEndElement(/* ExperimentDescription */);
         xw.WriteStartElement("SessionDescription");
         xw.WriteElementString("Date", head.Date);
         xw.WriteElementString("Time", head.Time);
         xw.WriteElementString("Subject", head.Subject.ToString("0000"));
         xw.WriteElementString("Agent", head.Agent.ToString("0000"));
         foreach (string tech in head.Technician)
             xw.WriteElementString("Technician", tech);
         if(head.OtherSessionInfo != null)
             foreach (KeyValuePair<string, string> other in head.OtherSessionInfo)
             {
                 xw.WriteStartElement("Other");
                 xw.WriteAttributeString("Name", other.Key);
                 xw.WriteString(other.Value);
                 xw.WriteEndElement(/* Other */);
             }
         xw.WriteElementString("BDFFile", head.BDFFile);
         xw.WriteElementString("EventFile", head.EventFile);
         xw.WriteElementString("ElectrodeFile", head.ElectrodeFile);
         if (head.Comment != null && head.Comment != "")
             xw.WriteElementString("Comment", head.Comment);
         xw.WriteEndElement(/* SessionDescription */);
         xw.WriteEndElement(/* Header */);
         xw.Close();
     }
     catch (Exception x)
     {
         throw new Exception("HeaderFileWriter: " + x.Message);
     }
 }