/////////////////////////////////////////////////////////////////////////////// // Methods for doing main class job // /////////////////////////////////////////////////////////////////////////////// #region PRIVATEMETHODS /// <summary> /// Writes given fixation data into the data sets fixation tables. /// </summary> /// <param name="fixationToSave">Fixation to be written to database</param> private void SaveFixationToTable(Fixation fixationToSave) { DataTable fixTable = null; if (fixationToSave.SampleType == (fixationToSave.SampleType | SampleType.Gaze)) { fixTable = Document.ActiveDocument.DocDataSet.GazeFixations; } else if (fixationToSave.SampleType == (fixationToSave.SampleType | SampleType.Mouse)) { fixTable = Document.ActiveDocument.DocDataSet.MouseFixations; } // Create New Fixation DataRow DataRow workRowFixationData; workRowFixationData = fixTable.NewRow(); // Fill with Data workRowFixationData["SubjectName"] = fixationToSave.SubjectName; workRowFixationData["TrialID"] = fixationToSave.TrialID; workRowFixationData["TrialSequence"] = fixationToSave.TrialSequence; workRowFixationData["CountInTrial"] = fixationToSave.CountInTrial; workRowFixationData["StartTime"] = fixationToSave.StartTime; workRowFixationData["Length"] = fixationToSave.Length; workRowFixationData["PosX"] = fixationToSave.PosX; workRowFixationData["PosY"] = fixationToSave.PosY; // Write into DB try { fixTable.Rows.Add(workRowFixationData); } catch (Exception ex) { ExceptionMethods.HandleException(ex); } }
/// <summary> /// Calculates fixations from raw data and writes them into /// the database in the fixations tables. /// </summary> /// <param name="sampleType">The <see cref="SampleType"/> of the data, gaze or mouse</param> /// <param name="subject">A <see cref="String"/> with the subject name</param> /// <param name="trialsTable">The database trials <see cref="DataTable"/></param> /// <param name="worker">The <see cref="BackgroundWorker"/> of the calculation</param> /// <param name="e">The <see cref="DoWorkEventArgs"/> of the <see cref="BackgroundWorker"/></param> public void CalcFixations( SampleType sampleType, string subject, System.Data.DataTable trialsTable, BackgroundWorker worker, DoWorkEventArgs e) { // Fixation Calculating Objects ////////////////////////////////////////// FixationDetection objFixationDetection = new FixationDetection(); // Instantiate the delegate using the method as a parameter GetDataDelegate getDataMethod = null; int minSamples = 0; int maxDistance = 0; if (sampleType == (sampleType | SampleType.Gaze)) { getDataMethod = Queries.GetGazeData; minSamples = this.gazeMinSamples; maxDistance = this.gazeMaxDistance; } else if (sampleType == (sampleType | SampleType.Mouse)) { getDataMethod = Queries.GetMouseData; minSamples = this.mouseMinSamples; maxDistance = this.mouseMaxDistance; } bool point_found_delayed; /* sample gazepoint-found flag, */ /* min_fix_samples ago */ float x_delayed; /* sample gazepoint coordinates, */ float y_delayed; /* min_fix_samples ago */ float deviation_delayed; /* deviation of the gaze from the */ /* present fixation, */ /* min_fix_samples ago */ /* Fixation data - delayed: */ float x_fix_delayed = new float(); /* fixation point as estimated */ float y_fix_delayed = new float(); /* min_fix_samples ago */ int saccade_duration_delayed; /* duration of the saccade */ /* preceeding the preset fixation */ /* (samples) */ long fix_start_time = new long(); int fix_duration_delayed_samples = new int(); /* duration of the present fixation */ long fix_duration_delayed_milliseconds = new long(); /* duration of the present fixation */ EyeMotionState currentState = new EyeMotionState(); // OtherVars int counterTrial = 0; PointF trialLastFixCenter = new PointF(0, 0); // Loop Rows=Trials foreach (DataRow trialRow in trialsTable.Rows) { List<Fixation> fixations = new List<Fixation>(); // Reinitialize Fixation detection object // to ensure no overlay between fixations of // trials that follow each other. objFixationDetection.InitFixation(minSamples); int trialID = (int)trialRow["TrialID"]; int trialSequence = (int)trialRow["TrialSequence"]; // Holds RawData corresponding to selected trial and subject DataTable rawDataTable = Queries.GetRawDataBySubjectAndTrialSequence(subject, trialSequence); long trialStartTime = rawDataTable.Rows.Count > 0 ? (long)rawDataTable.Rows[0]["Time"] : 0; int counterRows = 0; int counterFix = 0; bool isFixation = false; // Loop RawData foreach (DataRow rowRaw in rawDataTable.Rows) { PointF? newPt; SampleValidity isValidData = getDataMethod( rowRaw, Document.ActiveDocument.PresentationSize, out newPt); bool useSample = false; switch (isValidData) { case SampleValidity.Valid: useSample = true; break; case SampleValidity.Empty: useSample = true; break; case SampleValidity.Null: break; case SampleValidity.OutOfStimulus: useSample = true; break; } if (useSample) { PointF dataPoint = newPt.Value; currentState = objFixationDetection.DetectFixation( dataPoint.IsEmpty ? false : true, Convert.ToInt64(rowRaw[3]), dataPoint.X, dataPoint.Y, maxDistance, minSamples, out point_found_delayed, out x_delayed, out y_delayed, out deviation_delayed, out x_fix_delayed, out y_fix_delayed, out saccade_duration_delayed, out fix_start_time, out fix_duration_delayed_milliseconds, out fix_duration_delayed_samples); switch (currentState) { case EyeMotionState.FIXATING: if (!isFixation) { isFixation = true; } break; case EyeMotionState.FIXATION_COMPLETED: PointF fixationCenter = new PointF(x_fix_delayed, y_fix_delayed); // if (!Queries.OutOfScreen(fixationCenter)) TODO { Fixation completedFixation = new Fixation(); completedFixation.CountInTrial = counterFix + 1; completedFixation.Length = fix_duration_delayed_milliseconds; completedFixation.PosX = x_fix_delayed; completedFixation.PosY = y_fix_delayed; completedFixation.SampleType = sampleType; completedFixation.StartTime = fix_start_time - trialStartTime; completedFixation.SubjectName = (string)trialRow["SubjectName"]; completedFixation.TrialID = (int)trialRow["TrialID"]; completedFixation.TrialSequence = (int)trialRow["TrialSequence"]; if (this.eliminateFirstFixation && this.eliminateFirstFixationSimple == false && counterFix == 0 && VGPolyline.Distance(fixationCenter, trialLastFixCenter) < maxDistance && fix_duration_delayed_milliseconds < this.limitForFirstFixation) { // Eliminate if applicable } else if (this.eliminateFirstFixationSimple && counterFix == 0) { // do nothing, just go on with the next fixation eliminating this one counterFix++; } else { fixations.Add(completedFixation); counterFix++; } } isFixation = false; break; case EyeMotionState.ERROR: break; default: break; } } counterRows++; // End RawData Loop } // Save last Fix if it has not been saved by a following saccade if (isFixation && fix_duration_delayed_milliseconds > 0) { Fixation lastFixation = new Fixation(); lastFixation.CountInTrial = counterFix + 1; lastFixation.Length = fix_duration_delayed_milliseconds; lastFixation.PosX = x_fix_delayed; lastFixation.PosY = y_fix_delayed; lastFixation.SampleType = sampleType; lastFixation.StartTime = fix_start_time - trialStartTime; lastFixation.SubjectName = (string)trialRow["SubjectName"]; lastFixation.TrialID = (int)trialRow["TrialID"]; lastFixation.TrialSequence = (int)trialRow["TrialSequence"]; fixations.Add(lastFixation); } // Save last FixCenter for Eliminating first Fix of new trial if choosen in UI trialLastFixCenter.X = x_fix_delayed; trialLastFixCenter.Y = y_fix_delayed; if (this.mergeConsecutiveFixations) { // Look for consecutive fixations that are beneath each other // (within GazeMaxDistance) because of // miscalculation due to blinks or missing data. List<Fixation> mergedFixations = new List<Fixation>(); if (fixations.Count > 1) { Fixation foregoingFixation = fixations[0]; bool merged = false; int mergedCounter = 0; int consecutiveMerges = 0; int trialFixCounter = 1; PointF foregoingFixationCenter = new PointF(foregoingFixation.PosX, foregoingFixation.PosY); for (int i = 1; i < fixations.Count; i++) { // Test if consecutive calculated fixations lie in GazeMaxDistanceRange PointF fixationCenter = new PointF(fixations[i].PosX, fixations[i].PosY); int distance = (int)VGPolyline.Distance(foregoingFixationCenter, fixationCenter); if (distance < maxDistance) { long sumOfDuration = foregoingFixation.Length + fixations[i].Length; foregoingFixation.PosX = (foregoingFixation.PosX * foregoingFixation.Length + fixations[i].PosX * fixations[i].Length) / sumOfDuration; foregoingFixation.PosY = (foregoingFixation.PosY * foregoingFixation.Length + fixations[i].PosY * fixations[i].Length) / sumOfDuration; foregoingFixation.Length = fixations[i].StartTime - foregoingFixation.StartTime + fixations[i].Length; merged = true; mergedCounter++; consecutiveMerges++; } else { if (!merged) { foregoingFixation.CountInTrial = trialFixCounter; mergedFixations.Add(foregoingFixation); trialFixCounter++; } else { merged = false; foregoingFixation.CountInTrial -= mergedCounter - 1; foregoingFixation.CountInTrial = trialFixCounter; mergedFixations.Add(foregoingFixation); consecutiveMerges = 0; trialFixCounter++; } foregoingFixation = fixations[i]; foregoingFixationCenter = fixationCenter; } } if (!merged) { foregoingFixation.CountInTrial = trialFixCounter; mergedFixations.Add(foregoingFixation); trialFixCounter++; } } else { mergedFixations = fixations; } foreach (Fixation fixationToSave in mergedFixations) { this.SaveFixationToTable(fixationToSave); } } else { // Don not merge fixations, use the originals. foreach (Fixation fixationToSave in fixations) { this.SaveFixationToTable(fixationToSave); } } // increase TrialCounter counterTrial++; if (worker != null) { if (worker.CancellationPending) { e.Cancel = true; break; } else { // Report progress as a percentage of the total task. int percentComplete = Convert.ToInt32(Convert.ToSingle(counterTrial) / trialsTable.Rows.Count * 100); worker.ReportProgress(percentComplete); } } // End Trial Loop } // Save Data to MDF File this.WriteToMDF(sampleType); }
/// <summary> /// Calculates fixations from raw data and writes them into /// the database in the fixations tables. /// </summary> /// <param name="sampleType">The <see cref="SampleType"/> of the data, gaze or mouse</param> /// <param name="subject">A <see cref="String"/> with the subject name</param> /// <param name="trialsTable">The database trials <see cref="DataTable"/></param> /// <param name="worker">The <see cref="BackgroundWorker"/> of the calculation</param> /// <param name="e">The <see cref="DoWorkEventArgs"/> of the <see cref="BackgroundWorker"/></param> public void CalcFixations( SampleType sampleType, string subject, System.Data.DataTable trialsTable, BackgroundWorker worker, DoWorkEventArgs e) { // Fixation Calculating Objects ////////////////////////////////////////// FixationDetection objFixationDetection = new FixationDetection(); // Instantiate the delegate using the method as a parameter GetDataDelegate getDataMethod = null; int minSamples = 0; int maxDistance = 0; if (sampleType == (sampleType | SampleType.Gaze)) { getDataMethod = Queries.GetGazeData; minSamples = this.gazeMinSamples; maxDistance = this.gazeMaxDistance; } else if (sampleType == (sampleType | SampleType.Mouse)) { getDataMethod = Queries.GetMouseData; minSamples = this.mouseMinSamples; maxDistance = this.mouseMaxDistance; } bool point_found_delayed; /* sample gazepoint-found flag, */ /* min_fix_samples ago */ float x_delayed; /* sample gazepoint coordinates, */ float y_delayed; /* min_fix_samples ago */ float deviation_delayed; /* deviation of the gaze from the */ /* present fixation, */ /* min_fix_samples ago */ /* Fixation data - delayed: */ float x_fix_delayed = new float(); /* fixation point as estimated */ float y_fix_delayed = new float(); /* min_fix_samples ago */ int saccade_duration_delayed; /* duration of the saccade */ /* preceeding the preset fixation */ /* (samples) */ long fix_start_time = new long(); int fix_duration_delayed_samples = new int(); /* duration of the present fixation */ long fix_duration_delayed_milliseconds = new long(); /* duration of the present fixation */ EyeMotionState currentState = new EyeMotionState(); // OtherVars int counterTrial = 0; PointF trialLastFixCenter = new PointF(0, 0); // Loop Rows=Trials foreach (DataRow trialRow in trialsTable.Rows) { List <Fixation> fixations = new List <Fixation>(); // Reinitialize Fixation detection object // to ensure no overlay between fixations of // trials that follow each other. objFixationDetection.InitFixation(minSamples); int trialID = (int)trialRow["TrialID"]; int trialSequence = (int)trialRow["TrialSequence"]; // Holds RawData corresponding to selected trial and subject DataTable rawDataTable = Queries.GetRawDataBySubjectAndTrialSequence(subject, trialSequence); long trialStartTime = rawDataTable.Rows.Count > 0 ? (long)rawDataTable.Rows[0]["Time"] : 0; int counterRows = 0; int counterFix = 0; bool isFixation = false; // Loop RawData foreach (DataRow rowRaw in rawDataTable.Rows) { PointF? newPt; SampleValidity isValidData = getDataMethod( rowRaw, Document.ActiveDocument.PresentationSize, out newPt); bool useSample = false; switch (isValidData) { case SampleValidity.Valid: useSample = true; break; case SampleValidity.Empty: useSample = true; break; case SampleValidity.Null: break; case SampleValidity.OutOfStimulus: useSample = true; break; } if (useSample) { PointF dataPoint = newPt.Value; currentState = objFixationDetection.DetectFixation( dataPoint.IsEmpty ? false : true, Convert.ToInt64(rowRaw[3]), dataPoint.X, dataPoint.Y, maxDistance, minSamples, out point_found_delayed, out x_delayed, out y_delayed, out deviation_delayed, out x_fix_delayed, out y_fix_delayed, out saccade_duration_delayed, out fix_start_time, out fix_duration_delayed_milliseconds, out fix_duration_delayed_samples); switch (currentState) { case EyeMotionState.FIXATING: if (!isFixation) { isFixation = true; } break; case EyeMotionState.FIXATION_COMPLETED: PointF fixationCenter = new PointF(x_fix_delayed, y_fix_delayed); // if (!Queries.OutOfScreen(fixationCenter)) TODO { Fixation completedFixation = new Fixation(); completedFixation.CountInTrial = counterFix + 1; completedFixation.Length = fix_duration_delayed_milliseconds; completedFixation.PosX = x_fix_delayed; completedFixation.PosY = y_fix_delayed; completedFixation.SampleType = sampleType; completedFixation.StartTime = fix_start_time - trialStartTime; completedFixation.SubjectName = (string)trialRow["SubjectName"]; completedFixation.TrialID = (int)trialRow["TrialID"]; completedFixation.TrialSequence = (int)trialRow["TrialSequence"]; if (this.eliminateFirstFixation && this.eliminateFirstFixationSimple == false && counterFix == 0 && VGPolyline.Distance(fixationCenter, trialLastFixCenter) < maxDistance && fix_duration_delayed_milliseconds < this.limitForFirstFixation) { // Eliminate if applicable } else if (this.eliminateFirstFixationSimple && counterFix == 0) { // do nothing, just go on with the next fixation eliminating this one counterFix++; } else { fixations.Add(completedFixation); counterFix++; } } isFixation = false; break; case EyeMotionState.ERROR: break; default: break; } } counterRows++; // End RawData Loop } // Save last Fix if it has not been saved by a following saccade if (isFixation && fix_duration_delayed_milliseconds > 0) { Fixation lastFixation = new Fixation(); lastFixation.CountInTrial = counterFix + 1; lastFixation.Length = fix_duration_delayed_milliseconds; lastFixation.PosX = x_fix_delayed; lastFixation.PosY = y_fix_delayed; lastFixation.SampleType = sampleType; lastFixation.StartTime = fix_start_time - trialStartTime; lastFixation.SubjectName = (string)trialRow["SubjectName"]; lastFixation.TrialID = (int)trialRow["TrialID"]; lastFixation.TrialSequence = (int)trialRow["TrialSequence"]; fixations.Add(lastFixation); } // Save last FixCenter for Eliminating first Fix of new trial if choosen in UI trialLastFixCenter.X = x_fix_delayed; trialLastFixCenter.Y = y_fix_delayed; if (this.mergeConsecutiveFixations) { // Look for consecutive fixations that are beneath each other // (within GazeMaxDistance) because of // miscalculation due to blinks or missing data. List <Fixation> mergedFixations = new List <Fixation>(); if (fixations.Count > 1) { Fixation foregoingFixation = fixations[0]; bool merged = false; int mergedCounter = 0; int consecutiveMerges = 0; int trialFixCounter = 1; PointF foregoingFixationCenter = new PointF(foregoingFixation.PosX, foregoingFixation.PosY); for (int i = 1; i < fixations.Count; i++) { // Test if consecutive calculated fixations lie in GazeMaxDistanceRange PointF fixationCenter = new PointF(fixations[i].PosX, fixations[i].PosY); int distance = (int)VGPolyline.Distance(foregoingFixationCenter, fixationCenter); if (distance < maxDistance) { long sumOfDuration = foregoingFixation.Length + fixations[i].Length; foregoingFixation.PosX = (foregoingFixation.PosX * foregoingFixation.Length + fixations[i].PosX * fixations[i].Length) / sumOfDuration; foregoingFixation.PosY = (foregoingFixation.PosY * foregoingFixation.Length + fixations[i].PosY * fixations[i].Length) / sumOfDuration; foregoingFixation.Length = fixations[i].StartTime - foregoingFixation.StartTime + fixations[i].Length; merged = true; mergedCounter++; consecutiveMerges++; } else { if (!merged) { foregoingFixation.CountInTrial = trialFixCounter; mergedFixations.Add(foregoingFixation); trialFixCounter++; } else { merged = false; foregoingFixation.CountInTrial -= mergedCounter - 1; foregoingFixation.CountInTrial = trialFixCounter; mergedFixations.Add(foregoingFixation); consecutiveMerges = 0; trialFixCounter++; } foregoingFixation = fixations[i]; foregoingFixationCenter = fixationCenter; } } if (!merged) { foregoingFixation.CountInTrial = trialFixCounter; mergedFixations.Add(foregoingFixation); trialFixCounter++; } } else { mergedFixations = fixations; } foreach (Fixation fixationToSave in mergedFixations) { this.SaveFixationToTable(fixationToSave); } } else { // Don not merge fixations, use the originals. foreach (Fixation fixationToSave in fixations) { this.SaveFixationToTable(fixationToSave); } } // increase TrialCounter counterTrial++; if (worker != null) { if (worker.CancellationPending) { e.Cancel = true; break; } else { // Report progress as a percentage of the total task. int percentComplete = Convert.ToInt32(Convert.ToSingle(counterTrial) / trialsTable.Rows.Count * 100); worker.ReportProgress(percentComplete); } } // End Trial Loop } // Save Data to MDF File this.WriteToMDF(sampleType); }