public GVSectionViewModel(NavigationController controller, LegSectionViewModel prev, int number) : base(controller, prev) { ListNumber = number; StructureSource = new ObservableCollection <LegPartDbStructure>(Data.GV.LevelStructures(number).ToList()); foreach (var structure in StructureSource) { structure.Metrics = Data.Metrics.GetStr(structure.Size); } AddCustomObject(typeof(GVStructure)); AddNextPartObject(typeof(GVStructure)); AddEmpty(typeof(GVStructure)); CurrentEntry = new GVEntry(); }
public void Execute(object sender, DoWorkEventArgs e) { bw = (BackgroundWorker)sender; bw.ReportProgress(0, "Starting BDFConverter"); CCIUtilities.Log.writeToLog("Starting BDFConverter on records in " + directory); /***** Read electrode file *****/ ElectrodeInputFileStream etrFile = new ElectrodeInputFileStream( new FileStream(Path.Combine(directory, eventHeader.ElectrodeFile), FileMode.Open, FileAccess.Read)); /***** Open BDF file *****/ Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog(); dlg.Title = "Save as BDF file ..."; dlg.AddExtension = true; dlg.DefaultExt = ".bdf"; // Default file extension dlg.Filter = "BDF Files (.bdf)|*.bdf"; // Filter files by extension dlg.FileName = Path.GetFileNameWithoutExtension(eventHeader.BDFFile); bool? result = dlg.ShowDialog(); if (result == false) { e.Result = new int[] { 0, 0 }; return; } samplingRate = BDF.NSamp / BDF.RecordDuration; //Old sampling rate; exact as number of samples and duration are always an exact multiple oldOffsetInPts = Convert.ToInt32(offset * samplingRate); int newSamplingRate = (int)((double)samplingRate / (double)decimation + 0.5); //Make best estimate possible with integers newOffsetInPts = Convert.ToInt32(offset * newSamplingRate); newRecordLength = length * newSamplingRate; //new record length must be exact multiple of the sampling rate in BDF newStatus = new int[newRecordLength]; status = new int[BDF.NSamp]; GV0 = GV[0]; BDFWriter = new BDFEDFFileWriter(File.Open(dlg.FileName, FileMode.Create, FileAccess.ReadWrite), channels.Count + 1, /* Extra channel will have group variable value in it */ length, /* Record length in seconds, must be integer */ newSamplingRate, true); log = new LogFile(dlg.FileName + ".log.xml"); bigBuff = new float[BDF.NumberOfChannels - 1, newRecordLength]; //have to dimension to old channels rather than new //in case we need for reference calculations later /***** Create BDF header record *****/ BDFWriter.LocalRecordingId = BDF.LocalRecordingId; BDFWriter.LocalSubjectId = BDF.LocalSubjectId; int chan; for (int i = 0; i < channels.Count; i++) { chan = channels[i]; BDFWriter.channelLabel(i, BDF.channelLabel(chan)); BDFWriter.transducer(i, BDF.transducer(chan)); BDFWriter.dimension(i, BDF.dimension(chan)); BDFWriter.pMax(i, BDF.pMax(chan)); BDFWriter.pMin(i, BDF.pMin(chan)); BDFWriter.dMax(i, BDF.dMax(chan)); BDFWriter.dMin(i, BDF.dMin(chan)); BDFWriter.prefilter(i, BDF.prefilter(chan)); } chan = channels.Count; BDFWriter.channelLabel(chan, GV0.Name); //Make entries for old Status channel BDFWriter.transducer(chan, "None"); BDFWriter.dimension(chan, ""); BDFWriter.pMax(chan, 262143); BDFWriter.pMin(chan, -262144); BDFWriter.dMax(chan, 262143); BDFWriter.dMin(chan, -262144); BDFWriter.prefilter(chan, "None"); log.registerHeader(this); /***** Open Event file for reading *****/ EventFactory.Instance(eventHeader.Events); // set up the factory EventFileReader EventFR = new EventFileReader( new FileStream(Path.Combine(directory, eventHeader.EventFile), FileMode.Open, FileAccess.Read)); BDFLoc stp = BDF.LocationFactory.New(); BDFLoc lastEvent = BDF.LocationFactory.New(); if (!EDE.intrinsic) //set threshold if (risingEdge) threshold = EDE.channelMin + (EDE.channelMax - EDE.channelMin) * threshold; else threshold = EDE.channelMax - (EDE.channelMax - EDE.channelMin) * threshold; nominalT = BDF.LocationFactory.New(); //nominal Event time based on Event.Time actualT = BDF.LocationFactory.New(); //actual Event time in Status channel //Note: these should be the same if the two clocks run the same rate (DAQ and computer) /***** MAIN LOOP *****/ foreach (InputEvent ie in EventFR) //Loop through Event file { bw.ReportProgress(0, "Processing event " + ie.Index.ToString("0")); //Report progress if (ie.Name == EDE.Name) // Event match found in Event file { if(findEvent(ref stp, ie)) if (allSamps) //this is a continuous copy, not Event generated episodic conversion { runBDFtoEvent(lastEvent, ref stp, ie); lastEvent = BDF.LocationFactory.New(); } else createBDFRecord(stp, ie); //Create BDF recordset around this point; i.e. Event generated episodic conversion } } if (allSamps) //copy out to end of file { stp.Rec = BDF.NumberOfRecords; stp.Pt = 0; runBDFtoEvent(lastEvent, ref stp, null); } e.Result = new int[] { BDFWriter.NumberOfRecords, BDFWriter.NumberOfRecords }; BDFWriter.Close(); EventFR.Close(); log.Close(); }
/// <summary> /// Add a new GV to the Header or return previously entered one /// </summary> /// <param name="name">Name of the GV</param> /// <param name="description">Description of the GV</param> /// <param name="valueName"></param> /// <param name="val"></param> /// <returns></returns> public GVEntry AddOrGetGroupVar(string name, string description = "", string[] valueName = null, int[] val = null) { if (!GroupVars.ContainsKey(name)) { GVEntry gve = new GVEntry(); gve.Description = description; if (valueName != null && valueName.Length > 0) { gve.GVValueDictionary = new Dictionary<string, int>(valueName.Length); for (int i = 0; i < valueName.Length; i++) gve.GVValueDictionary.Add(valueName[i], val == null ? i + 1 : val[i]); } GroupVars.Add(name, gve); return gve; } else return GroupVars[name]; }
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); } }
//Process the PK events found: returns true if files succesfully written private bool ProcessEvents() { //GV 1 if (!head.GroupVars.ContainsKey("Source channel")) { GVEntry gve = new GVEntry(); gve.GVValueDictionary = new Dictionary<string, int>(); gve.Description = "Source channel for this Event"; foreach (ChannelItem ci in ChannelEntries.Items) { //create GV Value entry for each channel name channelOptions co = channels[ci.Channel.SelectedIndex]; int i; gve.GVValueDictionary.TryGetValue(co.name, out i); if (i == 0) gve.GVValueDictionary.Add(co.name, co.channel + 1); //Use "external" (1-based) channel numbering } head.GroupVars.Add("Source channel", gve); //Channel name: add to GV list in HDR newGVList[0] = gve; } else newGVList[0] = head.GroupVars["Source channel"]; //GV 2 newGVList[1] = head.AddOrGetGroupVar("Found fit", "Found satisfactory fit to PK signal", new string[] { "Found", "Not found" }); //GV 3 newGVList[2] = head.AddOrGetGroupVar("Magnitude", "Estimate of the magnitude of PK signal in scale of channel"); //GV 4 newGVList[3] = head.AddOrGetGroupVar("Direction", "Direction of PK signal", new string[] { "Positive", "Negative" }); //GV 5 newGVList[4] = head.AddOrGetGroupVar("Alpha TC", "Estimate of the time constant (in millisecs) for the rising edge of the PK signal"); //GV 6 newGVList[5] = head.AddOrGetGroupVar("Chi square", "Chi square estimate of goodness of fit to the PK signal"); //GV 7 newGVList[6] = head.AddOrGetGroupVar("Serial number", "Serial number for this channel/filter combination"); //GV 8 newGVList[7] = head.AddOrGetGroupVar("Trend degree", "Degree of trend removal of original PK signal plus 2"); //GV 9 newGVList[8] = head.AddOrGetGroupVar("Filter length", "Length of filter in points"); //GV 10 newGVList[9] = head.AddOrGetGroupVar("Threshold", "Capturing threshold in microV/sec"); //GV 11 newGVList[10] = head.AddOrGetGroupVar("Minimum length", "Minimum length of above-threshold filter signal in points"); //Create Event Dictionary entry for each new PK event/ChannelItem foreach (ChannelItem ci in ChannelEntries.Items) { EventDictionaryEntry ede = head.AddNewEvent(ci.ImpliedEventName, "PK detector events from PKDetectorAnalyzer based on channel " + ci.Channel.Text, newGVList); ede.BDFBased = true; //naked Event with clock BDF-based } head.Comment += (head.Comment == "" ? "" : Environment.NewLine) + "PK source Events added on " + DateTime.Now.ToString("dd MMM yyyy HH:mm:ss") + " by " + Environment.UserName; //Now read old Event file events = new List<Event.OutputEvent>(); Event.EventFactory.Instance(head.Events); // set up Event factory, based on EventDictionary in HDR EventFileReader efr = new EventFileReader( new FileStream(System.IO.Path.Combine(directory, head.EventFile), FileMode.Open, FileAccess.Read)); // open Event file bool zeroSet = false; foreach (Event.InputEvent ie in efr) // read in all Events into dictionary { events.Add(new Event.OutputEvent(ie)); //make list of all current Events if (!zeroSet && ie.IsCovered) //set zeroTime based on first encounter covered Event { bdf.setZeroTime(ie); zeroSet = true; } } efr.Close(); //write out new HDR file FileStream fs = null; bool OK = false; while (!OK) { try { head.EventFile = newFileName + ".evt"; //now we can change Event file name and write out new HDR fs = new FileStream(System.IO.Path.Combine(directory, newFileName + ".hdr"), FileMode.CreateNew, FileAccess.Write); OK = true; } catch (IOException) //force only a new { Replace_dataset rd = new Replace_dataset(newFileName, this.FNExtension.Text); rd.WindowStartupLocation = WindowStartupLocation.CenterOwner; rd.Owner = this; rd.ShowDialog(); if (rd.Result > 0) { if (rd.Result == 3) //Exit { Status.Text = "Cancelled writing new dataset"; return false; } if (rd.Result == 1) //Yes { OK = true; fs = new FileStream(System.IO.Path.Combine(directory, newFileName + ".hdr"), FileMode.Create, FileAccess.Write); } else //N0: new extension, try again { this.FNExtension.Text = rd.NewExtension.Text; //this will also change newFileName } } } } new HeaderFileWriter(fs, head); foreach (eventTime et in eventTimeList) { double ST = bdf.SampleTime(et.channelNumber); //create a naked Event at this time Event.OutputEvent newEvent = new Event.OutputEvent(head.Events[et.channelItem.ImpliedEventName], (double)(et.t0 + et.startTime) * ST); //assign GV values to new event newEvent.GVValue = new string[11]; newEvent.GVValue[0] = bdf.channelLabel(et.channelNumber); newEvent.GVValue[1] = et.foundFit ? "Found" : "Not found"; newEvent.GVValue[2] = ((int)Math.Abs(et.A)).ToString("0"); newEvent.GVValue[3] = et.sign > 0 ? "Positive" : "Negative"; newEvent.GVValue[4] = ((int)(1000D / et.a)).ToString("0"); if (et.chiSquare < 2E9) newEvent.GVValue[5] = ((int)et.chiSquare).ToString("0"); else newEvent.GVValue[5] = "0"; newEvent.GVValue[6] = et.serialNumber.ToString("0"); newEvent.GVValue[7] = (et.trendDegree + 2).ToString("0"); newEvent.GVValue[8] = et.filterLength.ToString("0"); newEvent.GVValue[9] = ((int)(et.threshold / ST)).ToString("0"); newEvent.GVValue[10] = et.minimumLength.ToString("0"); events.Add(newEvent); } events = events.OrderBy(ev => bdf.timeFromBeginningOfFileTo(ev)).ToList(); //sort Events into time order fs = new FileStream(System.IO.Path.Combine(directory,head.EventFile), FileMode.Create, FileAccess.Write); EventFileWriter efw = new EventFileWriter(fs); foreach (Event.OutputEvent ev in events) efw.writeRecord(ev); efw.Close(); lf.Close(); //close out log file //and copy out to file logStream.WriteTo(new FileStream(System.IO.Path.Combine(directory, newFileName + ".pkda.log.xml"), FileMode.Create, FileAccess.Write)); return true; }