public void registerError(string message, InputEvent ie) { logStream.WriteStartElement("Error"); logStream.WriteAttributeString("Index", ie.Index.ToString("0")); logStream.WriteValue(message); logStream.WriteEndElement(/*Error*/); }
public void registerEpochSet(double epoch, InputEvent ie) { logStream.WriteStartElement("EpochSet"); logStream.WriteAttributeString("EventIndex", ie.Index.ToString("0")); logStream.WriteValue(epoch.ToString("00000000000.0000000")); logStream.WriteEndElement(/*EpochSet*/); }
/// <summary> /// Calculates the time of start of file (record 0, point 0) based on the InputEvent. /// After this, value may be accessed via property <code>zeroTime</code> /// </summary> /// <param name="IE">InputEvent to use as index</param> /// <returns>True if GC found, false if not</returns> public bool setZeroTime(InputEvent IE) { int[] statusBuffer = new int[NSamp]; int rec = 0; uint mask = 0xFFFFFFFF >> (32 - EventFactory.Instance().statusBits); while (this.read(rec++) != null) { statusBuffer = getStatus(); for (int i = 0; i < NSamp; i++) if ((mask & statusBuffer[i]) == IE.GC) { _zeroTime = IE.Time - this.RecordDuration * (--rec + (double)i / NSamp); return true; } } return false; }
private bool findNextMark(EpisodeMark eventCriterium, IEnumerator<InputEvent> Events, bool startEvent, out double time, out InputEvent ie) { if (eventCriterium._Event.GetType() == typeof(string)) //handle special cases first { string str = (string)eventCriterium._Event; if (str == "Beginning of file") //may occur as start- or endEvent { time = 0D; ie = null; //only one with no additional GVs possible return true; } else if (str == "Same Event") //only occurs as endEvent { //will only be called if there has been a previous match ie = Events.Current; time = Events.Current.relativeTime; sameEventFlag = true; return true; } } //end special cases time = -1D; //default returns ie = null; bool more = true; //this allows a start Event to match the previously matched Event except in case of Same Event if (!startEvent || Events.Current == null || sameEventFlag) more = Events.MoveNext(); sameEventFlag = false; while(more) // loop through Events beginning at .Current to find one meeting eventCriterium { ie = Events.Current; if (eventCriterium._Event.GetType() == typeof(EventDictionaryEntry)) //if named Event, simply check it { if (eventCriterium.Match(ie)) //found matching Event { time = Events.Current.relativeTime; return true; } } else //anonymous Event { string str = eventCriterium.EventName(); if (str == "Any Event" || str.Substring(11) == "(all)" || ie.EDE.IsCovered) //make sure Any Event or if (eventCriterium.MatchGV(ie)) { time = Events.Current.relativeTime; return true; } } more = Events.MoveNext(); //move on to next Event } //while loop if (!startEvent) //if endEvent time is end of BDF file time = bdf.RecordDurationDouble * bdf.NumberOfRecords; return false; }
/// <summary> /// Copy constructor converting an InputEvent to OutputEvent to permit copying /// of Event file entries to create a new Event file /// </summary> /// <param name="ie">InputEvent to be copied</param> public OutputEvent(InputEvent ie) : base(ie.EDE) { m_time = ie.Time; m_index = ie.m_index; m_gc = ie.m_gc; if (ie.GVValue != null) {//do a full copy to protect values GVValue = new string[ie.EDE.GroupVars.Count]; //go back to HDR definition int i = 0; foreach (string v in ie.GVValue) GVValue[i++] = v; } else GVValue = null; }
public InputEvent CreateInputEvent(string name) { EventDictionaryEntry ede; if (name == null || !ed.TryGetValue(name, out ede)) throw new Exception("No entry in EventDictionary for \"" + name + "\""); InputEvent e = new InputEvent(ede); return e; }
private void runBDFtoEvent(BDFLoc lastEventLocation, ref BDFLoc nextEventLocation, InputEvent evt) { nextEventLocation += decimation - 1; //correct location so we know where to stop; warning: it's tricky! nextEventLocation.Pt /= decimation; //location should be next after actual Event to keep decimation on track nextEventLocation.Pt *= decimation; //this also works because decimation must be a factor of the record length int pt = lastEventLocation.Pt / decimation; int j = lastEventLocation.Pt; int k; int p = 0; double[] buff = new double[BDF.NumberOfChannels-1]; double[] references = null; if (referenceChannels != null) references = new double[referenceChannels.Count]; for (int rec = lastEventLocation.Rec; rec <= nextEventLocation.Rec; rec++) { if (BDF.read(rec) == null) return; // only happen on last call to fill out record if (rec == nextEventLocation.Rec) k = nextEventLocation.Pt; else k = BDF.NSamp; for (p = j; p < k; p += decimation, pt++) { for (int c = 0; c < BDF.NumberOfChannels - 1; c++) buff[c] = BDF.getSample(c, p); if (referenceChannels != null) // then some channels need reference correction { //First calculate all needed references for this point for (int i1 = 0; i1 < referenceChannels.Count; i1++) { references[i1] = 0.0D; //zero them out foreach (int chan in referenceChannels[i1]) references[i1] += buff[chan]; //add them up references[i1] /= (double)referenceChannels[i1].Count; //divide to get average } //Then, subtract them from each channel in each channel group float refer; for (int i1 = 0; i1 < referenceGroups.Count; i1++) { refer = (float)references[i1]; for (int i2 = 0; i2 < referenceGroups[i1].Count; i2++) buff[referenceGroups[i1][i2]] -= refer; } } for (int c = 0; c < BDFWriter.NumberOfChannels - 1; c++) BDFWriter.putSample(c, pt, (float)(buff[channels[c]])); newStatus[pt] = lastStatus; } if (rec != nextEventLocation.Rec) { BDFWriter.putStatus(newStatus); BDFWriter.write(); } j = 0; // OK because decimation has to be integer divisor of the sampling rate pt = 0; // so that these two remain in lock-step => no offset to calculate } /***** Get group variable for this record *****/ string s = evt.GVValue[EDE.GroupVars.FindIndex(n => n.Equals(GV0))]; //Find value for this GV if (GV0.GVValueDictionary != null) lastStatus = GV0.GVValueDictionary[s]; //Lookup in GV value dictionary to convert to integer else lastStatus = Convert.ToInt32(s); //Or not; value of GV numnber representing itself }
private void createBDFRecord(BDFLoc eventLocation, InputEvent evt) { BDFLoc startingPt = eventLocation + oldOffsetInPts; //calculate starting point if (startingPt.Rec < 0) return; //start of record outside of file coverage; so skip it BDFLoc endPt = startingPt + newRecordLength * decimation; //calculate ending point if (endPt.Rec >= BDF.NumberOfRecords) return; //end of record outside of file coverage /***** Read correct portion of BDF file and decimate *****/ int pt = 0; int j; int k; int p = 0; //set to avoid compiler complaining about uninitialized variable! for (int rec = startingPt.Rec; rec <= endPt.Rec; rec++) { if (BDF.read(rec) == null) throw new Exception("Unable to read BDF record #" + rec.ToString("0")); if (rec == startingPt.Rec) j = startingPt.Pt; else j = p - BDF.NSamp; // calculate point offset at beginning of new record, taking into account left over from decimation if (rec == endPt.Rec) k = endPt.Pt; else k = BDF.NSamp; for (p = j; p < k; p += decimation, pt++) for (int c = 0; c < BDF.NumberOfChannels - 1; c++) bigBuff[c, pt] = (float)BDF.getSample(c, p); } /***** Get group variable for this record and set Status channel values *****/ string s = evt.GVValue[EDE.GroupVars.FindIndex(n => n.Equals(GV0))]; //Find value for this GV newStatus[StatusMarkerType == 1 ? 0 : -newOffsetInPts] = GV0.ConvertGVValueStringToInteger(s); // then propagate throughout Status channel for (int i = (StatusMarkerType == 1 ? 1 : 1 - newOffsetInPts); i < newRecordLength; i++) newStatus[i] = newStatus[i - 1]; BDFWriter.putStatus(newStatus); /***** Calculate referenced data *****/ calculateReferencedData(); /***** Write out record after loading appropriate data *****/ for (int iChan = 0; iChan < BDFWriter.NumberOfChannels - 1; iChan++) { int channel = channels[iChan]; // translate channel numbers double ave = 0.0; double beta = 0.0; double fn = (double)newRecordLength; if (radinOffset) //calculate Radin offset for this channel, based on a segment of the data specified by radinLow and radinHigh { for (int i = radinLow; i < radinHigh; i++) ave += bigBuff[channel, i]; ave = ave / (double)(radinHigh - radinLow); } if (removeOffsets || removeTrends) //calculate average for this channel { for (int i = 0; i < newRecordLength; i++) ave += bigBuff[channel, i]; ave = ave / fn; } double t = 0D; if (removeTrends) //calculate linear trend for this channel; see Bloomfield p. 115 //NOTE: this technique works only for "centered" data: if there are N points, covering NT seconds, it is assumed that // these points are located at (2i-N-1)T/2 seconds, for i = 1 to N; in other words, the samples are in the center of // each sample time and are symetrically distributed about a central zero time in the record. Then one can separately // calculate the mean and the slope and apply them together to remove a linear trend. This doesn't work for quadratic // or higher order trend removal however. { t = (fn - 1.0D) / 2.0D; fn *= fn * fn - 1D; for (int i = 0; i < newRecordLength; i++) beta += bigBuff[channel, i] * ((double)i - t); beta = 12.0D * beta / fn; } for (int i = 0; i < newRecordLength; i++) BDFWriter.putSample(iChan, i, bigBuff[channel, i] - (float)(ave + beta * ((double)i - t))); } BDFWriter.write(); }
private void createFILMANRecord(BDFLoc stp, InputEvent evt) { BDFLoc startingPt = stp + offsetInPts; //calculate starting point if (startingPt.Rec < 0) return; //start of record outside of file coverage; so skip it BDFLoc endPt = startingPt + Convert.ToInt32(length * samplingRate); //calculate ending point if (endPt.Rec >= BDF.NumberOfRecords) return; //end of record outside of file coverage /***** Read correct portion of BDF file and decimate *****/ int pt = 0; int j; int k; int p = 0; //set to avoid compiler complaining about uninitialized variable! for (int rec = startingPt.Rec; rec <= endPt.Rec; rec++) { if (BDF.read(rec) == null) throw new Exception("Unable to read BDF record #" + rec.ToString("0")); if (rec == startingPt.Rec) j = startingPt.Pt; else j = p - BDF.NSamp; // calculate point offset at beginning of new record if (rec == endPt.Rec) k = endPt.Pt; else k = BDF.NSamp; for (p = j; p < k; p += decimation, pt++) for (int c = 0; c < BDF.NumberOfChannels - 1; c++) bigBuff[c, pt] = (float)BDF.getSample(c, p); } //NOTE: after this point bigBuff containes all channels in BDF file, // includes all BDF records that contribute to this output record, // but has been decimated to include only those points that will actually be written out!!! // This is necessary because referencing channels may not be actually included in the recordSet. /***** Get group variable for this record *****/ int GrVar = 2; //Load up group variables foreach (GVEntry gve in GV) { string s = evt.GVValue[EDE.GroupVars.FindIndex(n => n.Equals(gve))]; //Find value for this GV FMStream.record.GV[GrVar++] = gve.ConvertGVValueStringToInteger(s); //Lookup in dictionary } /***** Include any ancillary data *****/ if (anc) { int w = 0; for (int i = 0; i < EDE.ancillarySize; i += 4) FMStream.record.ancillary[w++] = (((evt.ancillary[i] << 8) + evt.ancillary[i + 1] << 8) + evt.ancillary[i + 2] << 8) + evt.ancillary[i + 3]; //NOTE: does not change endian; works for little endian to little endian } /***** Update bigBuff to referenced data *****/ calculateReferencedData(); /***** Write out channel after loading appropriate data *****/ for (int iChan = 0; iChan < FMStream.NC; iChan++) { int channel = channels[iChan]; // translate channel numbers double ave = 0.0; double beta = 0.0; double fn = (double)FMStream.ND; if (radinOffset) //calculate Radin offset for this channel, based on a segment of the data specified by radinLow and radinHigh { for (int i = radinLow; i < radinHigh; i++) ave += bigBuff[channel, i]; ave = ave / (double)(radinHigh - radinLow); } if (removeOffsets || removeTrends) //calculate average for this channel; this will always be true if removeTrends true { for (int i = 0; i < FMStream.ND; i++) ave += bigBuff[channel, i]; ave = ave / fn; } double t = 0D; if (removeTrends) //calculate linear trend for this channel; see Bloomfield p. 115 //NOTE: this technique works only for "centered" data: if there are N points, covering NT seconds, it is assumed that // these points are located at (2i-N-1)T/2 seconds, for i = 1 to N; in other words, the samples are in the center of // each sample time and are symetrically distributed about a central zero time in the record. Then one can separately // calculate the mean and the slope and apply them together to remove a linear trend. This doesn't work for quadratic // or higher order trend removal however. { t = (fn - 1.0D) / 2.0D; fn *= fn * fn - 1D; for (int i = 0; i < FMStream.ND; i++) beta += bigBuff[channel, i] * ((double)i - t); beta = 12.0D * beta / fn; } for (int i = 0; i < FMStream.ND; i++) FMStream.record[i] = (double)bigBuff[channel, i] - (ave + beta * ((double)i - t)); FMStream.write(); //Channel number group variable taken care of here } }
protected bool findEvent(ref BDFLoc stp, InputEvent ie) { if (!setEpoch) //First Event of this type: calculate start time (epoch) of the first point in the BDF file { if (!findEvent(ie.GC, ref stp)) { log.registerError("No Status found for Event named " + EDE.Name, ie); stp.Rec = 0; stp.Pt = 0; //reset return false; } nominalT.Rec = actualT.Rec = stp.Rec; nominalT.Pt = actualT.Pt = stp.Pt; epoch = ie.Time - ((double)stp.Rec + (double)stp.Pt / (double)BDF.NSamp) * (double)BDF.RecordDuration; log.registerEpochSet(epoch, ie); setEpoch = true; } else //calculate Status search starting point { double t = ie.Time - epoch; //Calculate seconds from starting epoch nominalT.Rec = (int)(t / (double)BDF.RecordDuration); //Record number nominalT.Pt = (int)((t - (double)(nominalT.Rec * BDF.RecordDuration)) * (double)samplingRate); //Sample number if (continuousSearch) { stp.Rec = actualT.Rec; //start at last found Event stp.Pt = actualT.Pt; } else // find next Event by jumping near to it { stp.Rec = nominalT.Rec; stp.Pt = nominalT.Pt; stp -= samplingRate / 16 + 1; //start 1/16sec before estimated time of the event } if (!findEvent(ie.GC, ref stp)) // find the next Status event in BDF; returns with stp set to event location { log.registerError("Unable to locate Status for Event " + EDE.Name, ie); stp.Rec = actualT.Rec; //return to last previous found Event stp.Pt = actualT.Pt; return false; } actualT.Rec = stp.Rec; actualT.Pt = stp.Pt; } if (!EDE.intrinsic) if (!findExtrinsicEvent(ref stp, maxSearch)) { log.registerError("No extrinsic event found for Event " + EDE.Name, ie); return false; } else log.registerExtrinsicEvent(nominalT, actualT, stp, ie); else log.registerIntrinsicEvent(nominalT, actualT, ie); return true; }
public void registerExtrinsicEvent(BDFLoc nominal, BDFLoc actual, BDFLoc ext, InputEvent ie) { logStream.WriteStartElement("Event"); logStream.WriteAttributeString("Index", ie.Index.ToString("0")); double t0 = actual.ToSecs(); double nominalOffset = nominal.ToSecs() - t0; logStream.WriteElementString("ActualStatus", t0.ToString("0.000000")); logStream.WriteElementString("EventFileDiff", (nominal.ToSecs() - t0).ToString("0.000000")); logStream.WriteElementString("ExtrinsicEventDiff", (ext.ToSecs() - t0).ToString("0.000000")); logStream.WriteEndElement(/*Event*/); gatherStats(t0, nominalOffset); }
internal bool Match(InputEvent ev) { if (ev.Name == this.EventName()) //event type matches return (_GV == null || this.MatchGV(ev)); return false; }
/// <summary> /// Convenience method that looks up the value of the correct GV in an InputEvent /// </summary> /// <param name="ev">The InputEvent to compare GV fors</param> /// <returns></returns> internal bool MatchGV(InputEvent ev) { return (_GV == null || MatchGV(ev.GetIntValueForGVName(_GV.Name))); }