protected bool GeneratePlotsWithPython(FileInfo exportFile, DirectoryInfo workDir) { if (!PythonInstalled) { NotifyPythonNotFound("Could not find the python executable"); return(false); } var exeDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); if (exeDirectory == null) { OnErrorEvent("Unable to determine the path to the directory with the MSFileInfoScanner executable"); return(false); } var pythonScriptFile = new FileInfo(Path.Combine(exeDirectory, "MSFileInfoScanner_Plotter.py")); if (!pythonScriptFile.Exists) { OnErrorEvent("Python plotting script not found: " + pythonScriptFile.FullName); return(false); } var args = PathUtils.PossiblyQuotePath(pythonScriptFile.FullName) + " " + PathUtils.PossiblyQuotePath(exportFile.FullName); OnDebugEvent(string.Format("{0} {1}", PythonPath, args)); var progRunner = new ProgRunner { Arguments = args, CreateNoWindow = true, MonitoringInterval = 2000, Name = "PythonPlotter", Program = PythonPath, Repeat = false, RepeatHoldOffTime = 0, WorkDir = workDir.FullName }; RegisterEvents(progRunner); const int MAX_RUNTIME_SECONDS = 600; const int MONITOR_INTERVAL_MILLISECONDS = 1000; var runtimeExceeded = false; try { // Start the program executing progRunner.StartAndMonitorProgram(); var startTime = DateTime.UtcNow; // Loop until program is complete, or until MAX_RUNTIME_SECONDS seconds elapses while (progRunner.State != ProgRunner.States.NotMonitoring) { ProgRunner.SleepMilliseconds(MONITOR_INTERVAL_MILLISECONDS); if (DateTime.UtcNow.Subtract(startTime).TotalSeconds < MAX_RUNTIME_SECONDS) { continue; } OnErrorEvent(string.Format("Plot creation with Python has taken more than {0:F0} minutes; aborting", MAX_RUNTIME_SECONDS / 60.0)); progRunner.StopMonitoringProgram(kill: true); runtimeExceeded = true; break; } } catch (Exception ex) { OnErrorEvent("Exception creating plots using Python", ex); return(false); } if (runtimeExceeded) { return(false); } // Examine the exit code if (progRunner.ExitCode == 0) { var success = RenameTempPngFile(exportFile, workDir); return(success); } OnErrorEvent("Python ExitCode = " + progRunner.ExitCode); return(false); }
/// <summary> /// Call the Python script to create the plots /// </summary> /// <returns>True if success, otherwise false</returns> /// <remarks>Call ErrorHistogramsToPng and ErrorScatterPlotsToPng prior to calling this method</remarks> private bool GeneratePlotsWithPython(MetadataFileInfo metadataFileInfo) { if (!PythonInstalled) { NotifyPythonNotFound("Could not find the python executable"); return(false); } if (metadataFileInfo.BaseOutputFile.Directory == null) { OnErrorEvent("Unable to determine the parent directory of the base output file: " + metadataFileInfo.BaseOutputFile.FullName); return(false); } if (!metadataFileInfo.BaseOutputFile.Directory.Exists) { metadataFileInfo.BaseOutputFile.Directory.Create(); } var workDir = metadataFileInfo.BaseOutputFile.Directory.FullName; var exeDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); if (exeDirectory == null) { OnErrorEvent("Unable to determine the path to the directory with the PPMErrorCharter executable"); return(false); } var pythonScriptFile = new FileInfo(Path.Combine(exeDirectory, "PPMErrorCharter_Plotter.py")); if (!pythonScriptFile.Exists) { OnErrorEvent("Python plotting script not found: " + pythonScriptFile.FullName); return(false); } var baseOutputName = metadataFileInfo.BaseOutputFile.Name; var metadataFile = new FileInfo(Path.Combine(workDir, "MZRefinery_Plotting_Metadata.txt")); OnDebugEvent("Creating " + metadataFile.FullName); using (var writer = new StreamWriter(new FileStream(metadataFile.FullName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))) { var plotFilesDefined = 0; if (metadataFileInfo.HistogramPlotFile != null) { writer.WriteLine("HistogramPlotFilePath=" + metadataFileInfo.HistogramPlotFile.FullName); plotFilesDefined++; } if (metadataFileInfo.MassErrorPlotFile != null) { writer.WriteLine("MassErrorPlotFilePath=" + metadataFileInfo.MassErrorPlotFile.FullName); plotFilesDefined++; } if (plotFilesDefined < 2) { writer.WriteLine("BaseOutputName=" + baseOutputName); metadataFileInfo.HistogramPlotFile = new FileInfo(Path.Combine(metadataFileInfo.BaseOutputFile.FullName, baseOutputName + "_Histograms.png")); metadataFileInfo.MassErrorPlotFile = new FileInfo(Path.Combine(metadataFileInfo.BaseOutputFile.FullName, baseOutputName + "_MassErrors.png")); } writer.WriteLine("HistogramData=" + metadataFileInfo.ErrorHistogramsExportFileName); writer.WriteLine("MassErrorVsTimeData=" + metadataFileInfo.MassErrorVsTimeExportFileName); writer.WriteLine("MassErrorVsMassData=" + metadataFileInfo.MassErrorVsMassExportFileName); } var args = PathUtils.PossiblyQuotePath(pythonScriptFile.FullName) + " " + PathUtils.PossiblyQuotePath(metadataFile.FullName); OnDebugEvent("{0} {1}", PythonPath, args); var progRunner = new ProgRunner { Arguments = args, CreateNoWindow = true, MonitoringInterval = 2000, Name = "PythonPlotter", Program = PythonPath, Repeat = false, RepeatHoldOffTime = 0, WorkDir = workDir }; RegisterEvents(progRunner); const int MAX_RUNTIME_SECONDS = 600; const int MONITOR_INTERVAL_MILLISECONDS = 1000; var runtimeExceeded = false; try { // Start the program executing progRunner.StartAndMonitorProgram(); var startTime = DateTime.UtcNow; // Loop until program is complete, or until MAX_RUNTIME_SECONDS seconds elapses while (progRunner.State != ProgRunner.States.NotMonitoring) { ProgRunner.SleepMilliseconds(MONITOR_INTERVAL_MILLISECONDS); if (DateTime.UtcNow.Subtract(startTime).TotalSeconds < MAX_RUNTIME_SECONDS) { continue; } OnErrorEvent("Plot creation with Python has taken more than {0:F0} minutes; aborting", MAX_RUNTIME_SECONDS / 60.0); progRunner.StopMonitoringProgram(kill: true); runtimeExceeded = true; break; } } catch (Exception ex) { OnErrorEvent("Exception creating plots using Python", ex); return(false); } if (runtimeExceeded) { return(false); } // Examine the exit code if (progRunner.ExitCode == 0) { OnStatusEvent("Generated plots; see:\n " + metadataFileInfo.HistogramPlotFile?.FullName + "\nand\n " + metadataFileInfo.MassErrorPlotFile?.FullName); if (DeleteTempFiles) { // Delete the temp export files try { metadataFile.Delete(); File.Delete(Path.Combine(workDir, metadataFileInfo.ErrorHistogramsExportFileName)); File.Delete(Path.Combine(workDir, metadataFileInfo.MassErrorVsTimeExportFileName)); File.Delete(Path.Combine(workDir, metadataFileInfo.MassErrorVsMassExportFileName)); } catch (Exception ex) { OnErrorEvent("Error deleting files: " + ex.Message); } } else { ConsoleMsgUtils.ShowDebug("{0}\n {1}\n {2}\n {3}\n {4}", "Not deleting the following temporary files since debug mode is enabled", metadataFile.FullName, Path.Combine(workDir, metadataFileInfo.ErrorHistogramsExportFileName), Path.Combine(workDir, metadataFileInfo.MassErrorVsTimeExportFileName), Path.Combine(workDir, metadataFileInfo.MassErrorVsMassExportFileName)); } return(true); } OnErrorEvent("Python ExitCode = " + progRunner.ExitCode); return(false); }
private void TestRunProgram(string exeName, string cmdArgs, bool createNoWindow, bool writeConsoleOutput, int maxRuntimeSeconds, bool programAbortExpected) { const int MONITOR_INTERVAL_MSEC = 500; var utilityExe = new FileInfo(Path.Combine(UTILITIES_DIRECTORY, exeName)); if (!utilityExe.Exists) { Assert.Fail("Exe not found: " + utilityExe.FullName); } var processStats = new PRISMWin.ProcessStats(); var workDir = @"C:\Temp"; var tempDir = new DirectoryInfo(workDir); if (!tempDir.Exists) { tempDir.Create(); } var coreCount = processStats.GetCoreCount(); Console.WriteLine("Machine has {0} cores", coreCount); Assert.GreaterOrEqual(coreCount, 2, "Core count less than 2"); var progRunner = new ProgRunner { Arguments = cmdArgs, CreateNoWindow = createNoWindow, MonitoringInterval = MONITOR_INTERVAL_MSEC, Name = "ProgRunnerUnitTest", Program = utilityExe.FullName, Repeat = false, RepeatHoldOffTime = 0, WorkDir = workDir, CacheStandardOutput = false, EchoOutputToConsole = false, WriteConsoleOutputToFile = writeConsoleOutput, ConsoleOutputFileIncludesCommandLine = true }; progRunner.StartAndMonitorProgram(); var cachedProcessID = 0; var dtStartTime = DateTime.UtcNow; var abortProcess = false; while (progRunner.State != ProgRunner.States.NotMonitoring) { if (cachedProcessID == 0) { cachedProcessID = progRunner.PID; } ProgRunner.SleepMilliseconds(MONITOR_INTERVAL_MSEC / 2); try { if (cachedProcessID > 0) { var cpuUsage = processStats.GetCoreUsageByProcessID(cachedProcessID); Console.WriteLine("CPU Usage: " + cpuUsage); } } catch (Exception ex) { Console.WriteLine("Unable to get the core usage: {0}", ex.Message); } ProgRunner.SleepMilliseconds(MONITOR_INTERVAL_MSEC / 2); if (maxRuntimeSeconds > 0) { if (DateTime.UtcNow.Subtract(dtStartTime).TotalSeconds > maxRuntimeSeconds) { Console.WriteLine("Aborting ProcessID {0} since runtime has exceeded {1} seconds", cachedProcessID, maxRuntimeSeconds); abortProcess = true; } } if (abortProcess) { progRunner.StopMonitoringProgram(kill: true); } } processStats.ClearCachedPerformanceCounterForProcessID(cachedProcessID); if (writeConsoleOutput) { ProgRunner.SleepMilliseconds(250); var consoleOutputFilePath = progRunner.ConsoleOutputFilePath; Assert.IsNotEmpty(consoleOutputFilePath, "Console output file path is empty"); var consoleOutputFile = new FileInfo(consoleOutputFilePath); Assert.True(consoleOutputFile.Exists, "File not found: " + consoleOutputFilePath); var secondsSinceMidnight = (int)(DateTime.Now.Subtract(DateTime.Today).TotalSeconds); if (consoleOutputFile.DirectoryName == null) { Assert.Fail("Unable to determine the parent directory of " + consoleOutputFilePath); } var newFilePath = Path.Combine(consoleOutputFile.DirectoryName, Path.GetFileNameWithoutExtension(consoleOutputFilePath) + "_" + secondsSinceMidnight + ".txt"); consoleOutputFile.MoveTo(newFilePath); // Open the file and assure that the first line contains the .exe name using (var reader = new StreamReader(new FileStream(newFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))) { if (reader.EndOfStream) { Assert.Fail("The ConsoleOutput file is empty: " + newFilePath); } var dataLine = reader.ReadLine(); if (string.IsNullOrWhiteSpace(dataLine)) { Assert.Fail("The first line of the ConsoleOutput file is empty: " + newFilePath); } if (!dataLine.ToLower().Contains(exeName)) { Assert.Fail("The first line of the ConsoleOutput file does not contain " + exeName + ": " + newFilePath); } } } if (programAbortExpected) { Assert.True(abortProcess, "Process was expected to be aborted due to excessive runtime, but was not"); } else { Assert.False(abortProcess, "Process was aborted due to excessive runtime; this is unexpected"); } }