/// <summary> /// Parses all datapoints from the footprint-file. /// </summary> private void ParseData() { // Log _config.LogLine("Parsing data from file " + _config.Datafile + " ..."); // Read all data points from the file int counter = 0; using (StreamReader sr = new StreamReader(_config.Datafile)) { // Init line and skip first line string line = sr.ReadLine(); while ((line = sr.ReadLine()) != null) { // Skip empty lines if (string.IsNullOrWhiteSpace(line)) { continue; } // Parse the line into a new datapoint _datapoints.Add(new FootprintDatapoint(line)); // Count counter++; } } // Log _config.LogLine("Read " + counter + " datapoints!"); _config.LogLine("Aggregating service units ..."); // Build service units counter = 0; // Determine all relevant service unit identifiers Dictionary <FootprintDatapoint.FootPrintEntry, List <string> > groupIdents = _config.ServiceUnitIdents.ToDictionary(s => s, s => _datapoints.Select(d => d[s].ToString()).Distinct().ToList()); // Build all service units and add the corresponding datapoints foreach (var serviceUnitIdentSet in EnumerationHelpers.CrossProduct(groupIdents.Select(g => g.Value).ToList())) { // Get the types and values of the idents of this service unit var ident = groupIdents.Keys.Zip(serviceUnitIdentSet, (FootprintDatapoint.FootPrintEntry identType, string identValue) => new Tuple <FootprintDatapoint.FootPrintEntry, string>(identType, identValue)); // Get associated datapoints IEnumerable <FootprintDatapoint> datapoints = _datapoints.Where(d => ident.All(i => d[i.Item1].ToString() == i.Item2)); // Create the service unit and submit all datapoints associated with it if (datapoints.Any()) { _serviceUnits.Add(new ServiceUnit(ident, datapoints)); } // Count counter++; } // Log _config.LogLine("Data contained " + counter + " service units!"); _config.LogLine("Initializing scenario ..."); _config.Init(_datapoints); }
/// <summary> /// Initializes the config with the actual data. /// </summary> /// <param name="footprints">The actual data to be assessed with DEA.</param> public void Init(IEnumerable <FootprintDatapoint> footprints) { _initialized = true; if (Groups != null && Groups.Any()) { _groupsIndividuals = EnumerationHelpers.CrossProduct(Groups.Select(i => footprints.Select(d => new Tuple <FootprintDatapoint.FootPrintEntry, string>(i, d[i].ToString())).Distinct().ToList()).ToList()).ToList(); } else { _groupsIndividuals = new List <List <Tuple <FootprintDatapoint.FootPrintEntry, string> > >() { new List <Tuple <FootprintDatapoint.FootPrintEntry, string> >() } }; } #endregion }
/// <summary> /// Generates all specified scatter plots. /// </summary> /// <param name="basename">The base name to use for the scatter plot.</param> /// <param name="xyFootprintCombinations">The values to plot for the two axes.</param> /// <param name="groupBy">The values to group by.</param> public void PlotFootprintsScattered( string basename, List <FootprintScatterPlotData> xyFootprintCombinations, List <FootprintDatapoint.FootPrintEntry> groupBy) { // --> Prepare dat file LogLine("Preparing dat file(s) ..."); Dictionary <FootprintDatapoint.FootPrintEntry, int> datColumns = new Dictionary <FootprintDatapoint.FootPrintEntry, int>(); int currentIndex = 0; // Build dictionary of unique columns and indices for them foreach (var uniqueEntry in xyFootprintCombinations // X axis values .Select(t => t.XAxis) // Y axis values .Concat(xyFootprintCombinations.Select(t => t.YAxis)) // Heat info .Concat(xyFootprintCombinations.Where(e => e.Heat != null).Select(e => (FootprintDatapoint.FootPrintEntry)e.Heat)) // We only need every entry once .Distinct()) { datColumns[uniqueEntry] = ++currentIndex; } string singleDatFile = basename + ".dat"; // Group data (if required) Dictionary <List <Tuple <FootprintDatapoint.FootPrintEntry, string> >, string> dataGroups = // Check whether we need any grouping at all groupBy.Any() ? // Make cross product of the grouping combinations EnumerationHelpers.CrossProduct(groupBy.Select(i => _datapoints.Select(d => new Tuple <FootprintDatapoint.FootPrintEntry, string>(i, d[i].ToString())).Distinct().ToList()).ToList()) // Create a dictionary containing the actual tuple and the corresponding dat file name .ToDictionary(k => k, v => basename + string.Join("", v.Select(e => e.Item1 + e.Item2)) + ".dat") : // No grouping required - leave a null null; LogLine("Found " + (dataGroups != null ? dataGroups.Count : 1) + " group(s)!"); // Write dat file(s) if (dataGroups != null) { // Write file per data group foreach (var group in dataGroups) { using (StreamWriter sw = new StreamWriter(Path.Combine(OutputDirectory, group.Value))) { // Write header sw.Write(IOConstants.GNU_PLOT_COMMENT_LINE.ToString() + IOConstants.GNU_PLOT_VALUE_SPLIT.ToString()); foreach (var entry in datColumns.OrderBy(c => c.Value)) { sw.Write(entry.Key.ToString() + IOConstants.GNU_PLOT_VALUE_SPLIT); } sw.WriteLine(); // Write all entries foreach (var footprint in _datapoints.Where(d => group.Key.All(e => (d[e.Item1].ToString()) == e.Item2))) { foreach (var entry in datColumns.OrderBy(c => c.Value)) { sw.Write((Convert.ToDouble(footprint[entry.Key])).ToString(IOConstants.FORMATTER) + IOConstants.GNU_PLOT_VALUE_SPLIT); } sw.WriteLine(); } } } } else { // Write only a single file using (StreamWriter sw = new StreamWriter(Path.Combine(OutputDirectory, singleDatFile))) { // Write header sw.Write(IOConstants.GNU_PLOT_COMMENT_LINE.ToString() + IOConstants.GNU_PLOT_VALUE_SPLIT.ToString()); foreach (var entry in datColumns.OrderBy(c => c.Value)) { sw.Write(entry.Key.ToString() + IOConstants.GNU_PLOT_VALUE_SPLIT); } sw.WriteLine(); // Write all entries foreach (var footprint in _datapoints) { foreach (var entry in datColumns.OrderBy(c => c.Value)) { sw.Write((Convert.ToDouble(footprint[entry.Key])).ToString(IOConstants.FORMATTER) + IOConstants.GNU_PLOT_VALUE_SPLIT); } sw.WriteLine(); } } } // --> Prepare plot script LogLine("Preparing plot script ..."); string plotScript = basename + ".gp"; using (StreamWriter sw = new StreamWriter(Path.Combine(OutputDirectory, plotScript))) { sw.WriteLine("reset"); sw.WriteLine("# Output definition"); sw.WriteLine("set terminal pdfcairo enhanced size 7, 3 font \"Consolas, 12\""); sw.WriteLine("set output \"" + basename + ".pdf\""); sw.WriteLine("set lmargin 13"); sw.WriteLine("set rmargin 13"); sw.WriteLine("# Parameters"); sw.WriteLine("set key right top Right"); sw.WriteLine("set grid"); sw.WriteLine("set style fill solid 0.75"); string colorDefinition = DataProcessor.GenerateLineStyleScriptCodeWithPoints(); int colorCount = colorDefinition.Length - colorDefinition.Replace(IOConstants.LINE_TERMINATOR, string.Empty).Length - 1; sw.WriteLine(colorDefinition); // Make one diagram per given combination of characteristics foreach (var combination in xyFootprintCombinations) { sw.WriteLine("set title \"" + combination.XAxis + " / " + combination.YAxis + "\""); sw.WriteLine("set xlabel \"" + combination.XAxis + "\""); sw.WriteLine("set ylabel \"" + combination.YAxis + "\""); sw.WriteLine("plot \\"); if (dataGroups != null) { // Make separate plots for the groups int counter = 0; foreach (var dataGroup in dataGroups.OrderByAlphaNumeric(g => g.Value)) { if (++counter < dataGroups.Count) { sw.WriteLine("\"" + dataGroup.Value + "\"" + " u " + datColumns[combination.XAxis] + ":" + datColumns[combination.YAxis] + (combination.Heat == null ? "" : ":" + datColumns[(FootprintDatapoint.FootPrintEntry)combination.Heat]) + " w points linestyle " + ((counter % colorCount) + 1) + (combination.Heat == null ? "" : " palette") + " t \"" + string.Join("/", dataGroup.Key.Select(e => e.Item2)) + "\"" + ", \\"); } else { sw.WriteLine("\"" + dataGroup.Value + "\"" + " u " + datColumns[combination.XAxis] + ":" + datColumns[combination.YAxis] + (combination.Heat == null ? "" : ":" + datColumns[(FootprintDatapoint.FootPrintEntry)combination.Heat]) + " w points linestyle " + ((counter % colorCount) + 1) + (combination.Heat == null ? "" : " palette") + " t \"" + string.Join("/", dataGroup.Key.Select(e => e.Item2)) + "\""); } } } else { // Plot the overall data at once sw.WriteLine("\"" + singleDatFile + "\"" + " u " + datColumns[combination.XAxis] + ":" + datColumns[combination.YAxis] + (combination.Heat == null ? "" : ":" + datColumns[(FootprintDatapoint.FootPrintEntry)combination.Heat]) + " w points linestyle 1" + (combination.Heat == null ? "" : " palette") + " t \"Overall\""); } } sw.WriteLine("reset"); sw.WriteLine("exit"); } // --> Prepare command script LogLine("Preparing command script ..."); string commandScript = basename + ".cmd"; using (StreamWriter sw = new StreamWriter(Path.Combine(OutputDirectory, commandScript))) sw.WriteLine("gnuplot " + plotScript); // Log Console.WriteLine("Calling plot script ..."); // --> Execute plot script DataProcessor.ExecuteScript(Path.Combine(OutputDirectory, commandScript), (string msg) => { LogLine(msg); }); }
/// <summary> /// Asks a user for a directory and a seed-count then executes all combinations that can be obtained. /// </summary> static void ExecuteInstances() { // Ask for the directory to execute Console.WriteLine("Directory to execute [current]:"); string directory = Console.ReadLine().Trim(); if (!Directory.Exists(directory)) { directory = Directory.GetCurrentDirectory(); } // Ask for seed count uint seedCount = 1; Console.WriteLine("Number of seeds to execute [1]:"); try { seedCount = uint.Parse(Console.ReadLine()); } catch (FormatException) { } // Ask for degree of parallelism uint paraDeg = 1; Console.WriteLine("Degree of parallelism [1]:"); try { paraDeg = uint.Parse(Console.ReadLine()); } catch (FormatException) { } // Get all files List <string> instances = Directory.EnumerateFiles(directory, "*.xinst").Concat(Directory.EnumerateFiles(directory, "*.xlayo")).ToList(); List <string> settings = Directory.EnumerateFiles(directory, "*.xsett").ToList(); List <string> configs = Directory.EnumerateFiles(directory, "*.xconf").ToList(); List <string> seeds = Enumerable.Range(1, (int)seedCount).Select(s => s.ToString()).ToList(); var combinations = EnumerationHelpers.CrossProduct(new List <List <string> >() { instances, settings, configs, seeds }).ToList(); int counter = 0; if (paraDeg < 2) { foreach (var combination in combinations) { // Execute the next one Console.WriteLine("######################################"); Console.WriteLine("---> Executing combination " + (++counter).ToString() + " / " + combinations.Count()); Console.WriteLine("######################################"); Console.WriteLine("--> Calling wrapped RAWSimO.CLI ..."); string[] cliArgs = { combination[0], combination[1], combination[2], directory, combination[3] }; RAWSimO.CLI.Program.Main(cliArgs); Console.WriteLine("--> Returned from RAWSimO.CLI !"); Console.WriteLine("######################################"); } } else { // Prepare Console.WriteLine("######################################"); Console.WriteLine("---> Executing " + combinations.Count + " combinations in parallel"); Console.WriteLine("######################################"); string programName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "RAWSimO.CLI.exe"); int total = combinations.Count; int completed = 0; int started = 0; // Store last lines of all jobs and periodically log them for feedback List <string> lastLines = new List <string>(); Action log = () => { Console.WriteLine("Progress: " + started + "/" + completed + "/" + total + " (started/completed/total)"); lock (lastLines) for (int i = 0; i < lastLines.Count; i++) { Console.WriteLine(i + ": " + lastLines[i]); } }; Timer logTimer = new Timer(new TimerCallback((object unused) => { log(); }), null, 2000, 5000); // Execute jobs in parallel (limited by the given degree of parallelism) Parallel.ForEach(combinations, new ParallelOptions() { MaxDegreeOfParallelism = (int)paraDeg }, (List <string> combination) => { // Prepare sub-process string arguments = combination[0] + " " + combination[1] + " " + combination[2] + " " + directory + " " + combination[3]; ProcessStartInfo startInfo = new ProcessStartInfo(programName, arguments) { }; startInfo.UseShellExecute = false; startInfo.RedirectStandardOutput = true; int index = Interlocked.Increment(ref started) - 1; lock (lastLines) lastLines.Add("<null>"); Process process = new Process() { StartInfo = startInfo }; process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => { if (!string.IsNullOrWhiteSpace(e.Data)) { lastLines[index] = e.Data; } }; // Start the job process.Start(); process.BeginOutputReadLine(); // Wait for the job to finish process.WaitForExit(); Interlocked.Increment(ref completed); }); // Finish logging logTimer.Change(Timeout.Infinite, Timeout.Infinite); log(); } }