/// <summary> /// Analyzes the input file and writes the output to the AppConf.OutputFileName file. /// First checks if the output file already exists and if it is ok to overwrite it. /// </summary> /// <returns><c>true</c> if the analysis succeeded.</returns> public bool Analyze() { if (File.Exists(AppConf.OutputFileName) && !AppConf.OverWriteOutputFile) { ApplicationError.Add("Output file already exists", DefaultErrorMessageId); return(false); } return(PrepareEDFFiles() && _neuroLoopGain.Analyze()); }
/// <summary> /// Prepares the EDF files. /// Opens the input file, creates a new ouput file and sets the header information. /// </summary> /// <returns></returns> private bool PrepareEDFFiles() { if (AppConf.CopyInputSignal) { _neuroLoopGain.NumOutputSignals = 15; } else { _neuroLoopGain.NumOutputSignals = 14; } double[] sFrecs = new double[_neuroLoopGain.NumOutputSignals]; // Calculate best value for output EDF datablock duration according to analysis parameters try { //OPEN INPUT FILENAME _neuroLoopGain.InputEDFFile = new EdfFile(InputEDFFileName, true, false, false, true); _neuroLoopGain.InputSignalSelected = InputSignalSelected; int numInputSignals = _neuroLoopGain.InputEDFFile.FileInfo.NrSignals; _neuroLoopGain.InputBufferOffsets = new int[numInputSignals]; for (int k = 0; k < numInputSignals; k++) { _neuroLoopGain.InputBufferOffsets[k] = _neuroLoopGain.InputEDFFile.SignalInfo[k].BufferOffset; } //OUTPUT EDF EdfFile outputEDF = new EdfFile(AppConf.OutputFileName, false, false, false, false); //EdfFile outputEDF = new EdfFile(AppConf.OutputFileName, false, true, false, false); EdfSignalInfoBase edfSignalInfo = _neuroLoopGain.InputEDFFile.SignalInfo[InputSignalSelected]; outputEDF.CreateNewFile(_neuroLoopGain.NumOutputSignals); //PreCondition checked before: (1 / AppConf.SmoothTime) is between 1 and sFrecs[0] double doubleValue = MathEx.RoundNearest(1 / AppConf.SmoothTime); Range.EnsureRange(doubleValue, 0, _neuroLoopGain.InputSampleFrequency); for (int k = 0; k < _neuroLoopGain.NumOutputSignals; k++) { sFrecs[k] = doubleValue; } if (AppConf.CopyInputSignal) { sFrecs[0] = _neuroLoopGain.InputSampleFrequency; } //TODO: check this List <EdfDataBlockSizeCalculatorResult> results = new List <EdfDataBlockSizeCalculatorResult>(); double dataBlockDuration = EdfDataBlockSizeCalculator.Calculate(sFrecs, MaxEdFblockSize, results); if (!MathEx.SameValue(dataBlockDuration, -1)) { // Look for minimun possible error double bestError = results[0].MaxRelativeError; int bestIdx = 0; for (int k = 1; k < results.Count; k++) { if (results[k].MaxRelativeError < bestError) { bestError = results[k].MaxRelativeError; bestIdx = k; } else if (MathEx.SameValue(results[k].MaxRelativeError, bestError) && (results[k].Duration > results[bestIdx].Duration) && (results[k].Duration <= MaxBlockDuration)) { // Try to get block durations as much as possible to avoid excesive disk reads bestIdx = k; } } if (!MathEx.SameValue(bestError, 0)) { //TODO: error??, not valid SUSSsmoothingTime parameter (we're gonna miss some samples) ApplicationError.Add("not valid SmoothTime parameter (we're gonna miss some samples)", DefaultErrorMessageId); ErrorLogger.WriteErrorLog("not valid SmoothTime parameter (we're gonna miss some samples). Error = " + bestError.ToString()); outputEDF.FileInfo.SampleRecDuration = results[bestIdx].Duration; } else { outputEDF.FileInfo.SampleRecDuration = results[bestIdx].Duration; // Duration in seconds of block record AppConf.SmoothTime = 1.0 / sFrecs[1]; // Reset the value of SmoothTime to the one actually used by the system } } else { ApplicationError.Add("failed to assign a data block duration for output EDF", DefaultErrorMessageId); ErrorLogger.WriteErrorLog("failed to assign a data block duration for output EDF"); } _neuroLoopGain.OutputBufferOffsets = new int[15]; _neuroLoopGain.OutputBufferOffsets[0] = 0; for (int k = 0; k < _neuroLoopGain.NumOutputSignals; k++) { outputEDF.SignalInfo[k].PreFilter = edfSignalInfo.PreFilter; double nsamples = outputEDF.FileInfo.SampleRecDuration * sFrecs[k]; if (Math.Truncate(nsamples) < nsamples) { //TODO: Error?? the number of samples in a data block should be an integer number ApplicationError.Add("not valid SmoothTime parameter: we are going miss some samples", DefaultErrorMessageId); ErrorLogger.WriteErrorLog("not valid SmoothTime parameter: we are going miss some samples"); /* It should effectively be an integer number, but if we admit some error to happen * (bestError != 0), then we can work with the truncated value => we're gonna miss some * sample during the process */ nsamples = Math.Truncate(nsamples); } outputEDF.SignalInfo[k].NrSamples = (int)nsamples; //if (k == 0) if ((k == 0) && AppConf.CopyInputSignal) { outputEDF.SignalInfo[k].DigiMax = edfSignalInfo.DigiMax; outputEDF.SignalInfo[k].DigiMin = edfSignalInfo.DigiMin; outputEDF.SignalInfo[k].PhysiMax = edfSignalInfo.PhysiMax; outputEDF.SignalInfo[k].PhysiMin = edfSignalInfo.PhysiMin; outputEDF.SignalInfo[k].PhysiDim = edfSignalInfo.PhysiDim; } else { outputEDF.SignalInfo[k].DigiMax = short.MaxValue; outputEDF.SignalInfo[k].DigiMin = -short.MaxValue; //if (k < 9) if (k < _neuroLoopGain.NumOutputSignals - 6) { outputEDF.SignalInfo[k].PhysiDim = "Filtered"; outputEDF.SignalInfo[k].PhysiMax = short.MaxValue; outputEDF.SignalInfo[k].PhysiMin = -short.MaxValue; } else //if ((k >= 9) && (k < 12)) if ((k >= _neuroLoopGain.NumOutputSignals - 6) && (k < _neuroLoopGain.NumOutputSignals - 3)) { outputEDF.SignalInfo[k].PhysiMax = short.MaxValue; outputEDF.SignalInfo[k].PhysiMin = -short.MaxValue; } else { outputEDF.SignalInfo[k].PhysiDim = "%"; outputEDF.SignalInfo[k].PhysiMax = short.MaxValue / AppConf.MicGain; outputEDF.SignalInfo[k].PhysiMin = -short.MaxValue / AppConf.MicGain; } if (k > 0) { if (AppConf.CopyInputSignal) { _neuroLoopGain.OutputBufferOffsets[k] = _neuroLoopGain.OutputBufferOffsets[k - 1] + outputEDF.SignalInfo[k - 1].NrSamples; } else { _neuroLoopGain.OutputBufferOffsets[k + 1] = _neuroLoopGain.OutputBufferOffsets[k] + outputEDF.SignalInfo[k].NrSamples; } } } outputEDF.SignalInfo[k].Reserved = edfSignalInfo.Reserved; //if ((k > 0) && (k < 9)) if ((k >= _neuroLoopGain.NumOutputSignals - 14) && (k < _neuroLoopGain.NumOutputSignals - 6)) { if (AppConf.CopyInputSignal) { outputEDF.SignalInfo[k].SignalLabel = _signalOutputLabels[k] + " " + edfSignalInfo.PhysiDim + "**2/x"; } else { outputEDF.SignalInfo[k].SignalLabel = _signalOutputLabels[k + 1] + " " + edfSignalInfo.PhysiDim + "**2/x"; } } else if (AppConf.CopyInputSignal) { outputEDF.SignalInfo[k].SignalLabel = _signalOutputLabels[k]; } else { outputEDF.SignalInfo[k].SignalLabel = _signalOutputLabels[k + 1]; } outputEDF.SignalInfo[k].TransducerType = edfSignalInfo.TransducerType; outputEDF.SignalInfo[k].ThousandSeparator = edfSignalInfo.ThousandSeparator; } // Info for MC analysis outputEDF.FileInfo.Recording = string.Format(CultureInfo.InvariantCulture, "Startdate {0} NeuroLoop-gain analysis at {1:#.#}Hz of {2} in {3}", _neuroLoopGain.InputEDFFile.FileInfo.StartDate.HasValue ? _neuroLoopGain.InputEDFFile.FileInfo.StartDate.Value.ToString("dd-MMM-yyyy", CultureInfo.InvariantCulture) : "X", sFrecs[1], _neuroLoopGain.InputEDFFile.SignalInfo[InputSignalSelected].SignalLabel, Path.GetFileName(InputEDFFileName)); //Copy header info from the original signal outputEDF.FileInfo.Patient = _neuroLoopGain.InputEDFFile.FileInfo.Patient; outputEDF.FileInfo.StartDate = _neuroLoopGain.InputEDFFile.FileInfo.StartDate; outputEDF.FileInfo.StartTime = _neuroLoopGain.InputEDFFile.FileInfo.StartTime; outputEDF.CommitChanges(); _neuroLoopGain.MCsignalsBlockSamples = outputEDF.SignalInfo[1].NrSamples; _neuroLoopGain.OutputEDFFile = outputEDF; } catch (Exception e) { ApplicationError.Add("Error opening input and/or ouput files: " + e.Message, DefaultErrorMessageId); ErrorLogger.WriteErrorLog("Error opening input and/or ouput files: " + e.Message); } return(!ApplicationError.Signaled); }