| using System; |
| using System.Collections.Generic; |
| using System.ComponentModel; |
| using System.Data; |
| using System.Drawing; |
| using System.Text; |
| using System.Windows.Forms; |
| using System.Threading; |
| using System.Diagnostics; |
| using System.IO; |
| using System.Reflection; |
| |
| namespace distribution_explorer |
| { |
| /// <summary> |
| /// Main distribution explorer. |
| /// </summary> |
| public partial class DistexForm : Form |
| { |
| |
| EventLog log = new EventLog(); |
| /// <summary> |
| /// Main form |
| /// </summary> |
| public DistexForm() |
| { |
| if (!EventLog.SourceExists("EventLogDistex")) |
| { |
| EventLog.CreateEventSource("EventLogDistex", "Application"); |
| } |
| log.Source = "EventLogDistex"; |
| log.WriteEntry("DistexForm"); |
| |
| InitializeComponent(); |
| |
| Application.DoEvents(); |
| } |
| |
| private void Form_Load(object sender, EventArgs e) |
| { // Load distribution & parameters names, and default values. |
| try |
| { |
| // Create and show splash screen: |
| this.Hide(); |
| distexSplash frmSplash = new distexSplash(); |
| frmSplash.Show(); |
| frmSplash.Update(); |
| // Now load our data while the splash is showing: |
| if (boost_math.any_distribution.size() <= 0) |
| { |
| MessageBox.Show("Problem loading any distributions, size = " + boost_math.any_distribution.size().ToString()); |
| } |
| for (int i = 0; i < boost_math.any_distribution.size(); ++i) |
| { |
| distribution.Items.Add(boost_math.any_distribution.distribution_name(i)); |
| } |
| distribution.SelectedIndex = 0; // 1st in array, but could be any other. |
| // All parameters are made zero by default, but updated from chosen distribution. |
| parameter1.Text = boost_math.any_distribution.first_param_default(0).ToString(); |
| parameter2.Text = boost_math.any_distribution.second_param_default(0).ToString(); |
| parameter3.Text = boost_math.any_distribution.third_param_default(0).ToString(); |
| // |
| // Sleep and then close splash; |
| Thread.Sleep(3000); |
| frmSplash.Close(); |
| this.Visible = true; |
| } |
| catch |
| { // |
| log.WriteEntry("DistexForm_load exception!"); |
| MessageBox.Show("Problem loading distributions, size = " + boost_math.any_distribution.size().ToString()); |
| } |
| } |
| |
| private void distribution_SelectedIndexChanged(object sender, EventArgs e) |
| { |
| int i = distribution.SelectedIndex; // distribution tab. |
| parameter1Label.Text = boost_math.any_distribution.first_param_name(i); |
| parameterLabel1.Text = boost_math.any_distribution.first_param_name(i); // properties tab. |
| parameter2Label.Text = boost_math.any_distribution.second_param_name(i); |
| parameter3Label.Text = boost_math.any_distribution.third_param_name(i); |
| if (boost_math.any_distribution.first_param_name(i).Length.CompareTo(0) != 0) |
| { // Actually all the distributions have at least one parameters, |
| parameter1.Visible = true; // so should always be true. |
| parameterLabel1.Visible = true; |
| } |
| else |
| { // If distribution chosen has no parameter name(s) then hide. |
| parameter1.Visible = false; |
| parameterLabel1.Visible = false; |
| } |
| parameter1.Text = boost_math.any_distribution.first_param_default(i).ToString(); |
| // Update parameter default to match distribution. |
| if (boost_math.any_distribution.second_param_name(i).Length.CompareTo(0) != 0) |
| { |
| parameter2.Visible = true; |
| parameterLabel2.Visible = true; |
| parameter2ValueLabel.Visible = true; |
| } |
| else |
| { // hide |
| parameter2.Visible = false; |
| parameterLabel2.Visible = false; |
| parameter2ValueLabel.Visible = false; |
| |
| } |
| parameter2.Text = boost_math.any_distribution.second_param_default(i).ToString(); |
| if (boost_math.any_distribution.third_param_name(i).Length.CompareTo(0) != 0) |
| { |
| parameter3.Visible = true; |
| parameterLabel3.Visible = true; |
| parameter3ValueLabel.Visible = true; |
| } |
| else |
| { // hide |
| parameter3.Visible = false; |
| parameterLabel3.Visible = false; |
| parameter3ValueLabel.Visible = false; |
| } |
| parameter3.Text = boost_math.any_distribution.third_param_default(i).ToString(); |
| // Update tool tips to show total and supported ranges. |
| PropertiesTabPage.ToolTipText = "Shows properties and ranges of chosen distribution."; |
| } |
| |
| private boost_math.any_distribution dist; |
| |
| private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) |
| { // Display a grid of pdf, cdf... values from user's random variate x value. |
| try |
| { |
| if (e.ColumnIndex == 0) |
| { // Clicked on left-most random variate x column to enter a value. |
| int i = e.RowIndex; |
| string s = CDF_data.Rows[i].Cells[0].Value.ToString(); |
| double x = double.Parse(s); // Get value of users random variate x. |
| double pdf = dist.pdf(x); // Compute pdf values from x |
| double cdf = dist.cdf(x); // & cdf |
| double ccdf = dist.ccdf(x); // & complements. |
| CDF_data.Rows[i].Cells[1].Value = pdf; // and display values. |
| CDF_data.Rows[i].Cells[2].Value = cdf; |
| CDF_data.Rows[i].Cells[3].Value = ccdf; |
| } |
| } |
| catch (SystemException se) |
| { |
| MessageBox.Show("Error in random variable value: " + se.Message, "Calculation Error"); |
| } |
| } |
| |
| private void tabPage2_Enter(object sender, EventArgs e) |
| { // Properties tab shows distribution's mean, mode, median... |
| try |
| { // Show chosen distribution name, and parameter names & values. |
| int i = distribution.SelectedIndex; |
| distributionValueLabel.Text = boost_math.any_distribution.distribution_name(i).ToString(); |
| parameterLabel1.Text = boost_math.any_distribution.first_param_name(i).ToString(); |
| parameter1ValueLabel.Text = double.Parse(parameter1.Text).ToString(); |
| parameterLabel2.Text = boost_math.any_distribution.second_param_name(i).ToString(); |
| parameter2ValueLabel.Text = double.Parse(parameter2.Text).ToString(); |
| parameterLabel3.Text = boost_math.any_distribution.third_param_name(i).ToString(); |
| parameter3ValueLabel.Text = double.Parse(parameter3.Text).ToString(); |
| |
| // Show computed properties of distribution. |
| try |
| { |
| mean.Text = dist.mean().ToString(); |
| } |
| catch |
| { |
| mean.Text = "Undefined."; |
| } |
| try |
| { |
| mode.Text = dist.mode().ToString(); |
| } |
| catch |
| { |
| mode.Text = "Undefined."; |
| } |
| try |
| { |
| median.Text = dist.median().ToString(); |
| } |
| catch |
| { |
| median.Text = "Undefined."; |
| } |
| try |
| { |
| variance.Text = dist.variance().ToString(); |
| } |
| catch |
| { |
| variance.Text = "Undefined."; |
| } |
| try |
| { |
| standard_deviation.Text = dist.standard_deviation().ToString(); |
| } |
| catch |
| { |
| standard_deviation.Text = "Undefined."; |
| } |
| try |
| { |
| skewness.Text = dist.skewness().ToString(); |
| } |
| catch |
| { |
| skewness.Text = "Undefined."; |
| } |
| try |
| { |
| kurtosis.Text = dist.kurtosis().ToString(); |
| } |
| catch |
| { |
| kurtosis.Text = "Undefined."; |
| } |
| try |
| { |
| kurtosis_excess.Text = dist.kurtosis_excess().ToString(); |
| } |
| catch |
| { |
| kurtosis_excess.Text = "Undefined."; |
| } |
| try |
| { |
| coefficient_of_variation.Text = dist.coefficient_of_variation().ToString(); |
| } |
| catch |
| { |
| coefficient_of_variation.Text = "Undefined."; |
| } |
| |
| rangeLowestLabel.Text = dist.lowest().ToString(); |
| rangeGreatestLabel.Text = dist.uppermost().ToString(); |
| supportLowerLabel.Text = dist.lower().ToString(); |
| supportUpperLabel.Text = dist.upper().ToString(); |
| cdfTabPage.ToolTipText = "Random variate can range from " + rangeLowestLabel.Text |
| + " to " + rangeGreatestLabel.Text |
| + ",\nbut is said to be supported from " + supportLowerLabel.Text |
| + " to " + supportUpperLabel.Text |
| + "\nWithin this supported range the PDF and CDF have values between 0 and 1,\nbut below " + supportLowerLabel.Text + " both are zero, and above " |
| + supportUpperLabel.Text + " both are unity"; |
| } |
| catch (SystemException se) |
| { |
| MessageBox.Show(se.Message, "Calculation Error!"); |
| } |
| } |
| |
| private void properties_tab_Deselecting(object sender, TabControlCancelEventArgs e) |
| { |
| try |
| { |
| if (e.TabPageIndex == 0) |
| { // Update selected distribution object: |
| double x = double.Parse(parameter1.Text); |
| double y = double.Parse(parameter2.Text); |
| double z = double.Parse(parameter3.Text); |
| int i = distribution.SelectedIndex; |
| dist = new boost_math.any_distribution(i, x, y, z); |
| // Clear existing CDF data (has to be a better way?): |
| while (CDF_data.Rows.Count > 1) |
| { |
| CDF_data.Rows.Remove(CDF_data.Rows[0]); |
| } |
| // Clear existing quantile data (has to be a better way?): |
| while (QuantileData.Rows.Count > 1) |
| { |
| QuantileData.Rows.Remove(QuantileData.Rows[0]); |
| } |
| } |
| } |
| catch (SystemException se) |
| { |
| MessageBox.Show(se.Message + |
| " Please check the distribution's parameters and try again.", "Distribution Error"); |
| this.propertiesTab.SelectedIndex = 0; |
| e.Cancel = true; |
| } |
| } |
| |
| private void QuantileData_CellEndEdit(object sender, DataGridViewCellEventArgs e) |
| { // aka Risk & critical values tab. |
| try |
| { |
| if (e.ColumnIndex == 0) |
| { |
| int i = e.RowIndex; |
| string s = QuantileData.Rows[i].Cells[0].Value.ToString(); |
| double x = double.Parse(s); |
| // Remember x is alpha: 1 - the probability: |
| double lcv = dist.quantile(x); |
| double ucv = dist.quantile_c(x); |
| QuantileData.Rows[i].Cells[1].Value = lcv; |
| QuantileData.Rows[i].Cells[2].Value = ucv; |
| } |
| } |
| catch (SystemException se) |
| { |
| // TODO add some proper handling here! |
| MessageBox.Show("Error in probability value: " + se.Message, "Calculation Error"); |
| } |
| } |
| |
| private void QuantileTab_Enter(object sender, EventArgs e) |
| { // Evaluate critical values (quantiles) for pre-chosen risk level. |
| // and then, optionally, for other user-provided risk levels. |
| try |
| { |
| if (QuantileData.Rows.Count == 1) |
| { |
| // Add some defaults: |
| QuantileData.Rows.Add(5); // 5 Risk levels. |
| QuantileData.Rows[0].Cells[0].Value = "0.001"; // Risk values as text, |
| QuantileData.Rows[0].Cells[1].Value = dist.quantile(0.001); // & as double. |
| QuantileData.Rows[0].Cells[2].Value = dist.quantile_c(0.001); |
| QuantileData.Rows[1].Cells[0].Value = "0.01"; |
| QuantileData.Rows[1].Cells[1].Value = dist.quantile(0.01); // 99% confidence. |
| QuantileData.Rows[1].Cells[2].Value = dist.quantile_c(0.01); |
| QuantileData.Rows[2].Cells[0].Value = "0.05"; |
| QuantileData.Rows[2].Cells[1].Value = dist.quantile(0.05); |
| QuantileData.Rows[2].Cells[2].Value = dist.quantile_c(0.05); |
| QuantileData.Rows[3].Cells[0].Value = "0.1"; |
| QuantileData.Rows[3].Cells[1].Value = dist.quantile(0.1); |
| QuantileData.Rows[3].Cells[2].Value = dist.quantile_c(0.1); |
| QuantileData.Rows[4].Cells[0].Value = "0.33333333333333333"; |
| QuantileData.Rows[4].Cells[1].Value = dist.quantile(0.33333333333333333); |
| QuantileData.Rows[4].Cells[2].Value = dist.quantile_c(0.33333333333333333); |
| } |
| } |
| catch (SystemException se) |
| { |
| // TODO add some proper handling here! |
| MessageBox.Show(se.Message, "Calculation Error"); |
| } |
| } |
| |
| |
| private void properties_tab_SelectedIndexChanged(object sender, EventArgs e) |
| { |
| } |
| |
| private void tabPage1_Click(object sender, EventArgs e) |
| { |
| } |
| |
| private void CDF_data_CellContentClick(object sender, DataGridViewCellEventArgs e) |
| { |
| } |
| |
| distexAboutBox DistexAboutBox = new distexAboutBox(); |
| |
| private void aboutToolStripMenuItem_Click(object sender, EventArgs e) |
| { |
| DistexAboutBox.ShowDialog(); |
| } |
| |
| private void DistexForm_Activated(object sender, EventArgs e) |
| { |
| } |
| |
| /// get AssemblyDescription |
| public string AssemblyDescription |
| { |
| get |
| { |
| // Get all Description attributes on this assembly |
| object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); |
| // If there aren't any Description attributes, return an empty string |
| if (attributes.Length == 0) |
| return ""; |
| // If there is a Description attribute, return its value |
| return ((AssemblyDescriptionAttribute)attributes[0]).Description; |
| } |
| } |
| |
| private void saveFileDialog1_FileOk(object sender, CancelEventArgs e) |
| { |
| using (StreamWriter sw = new StreamWriter(this.saveFileDialog.FileName)) |
| { // Write distribution info and properties to file. |
| sw.WriteLine( AssemblyDescription); |
| sw.WriteLine("Version " + Assembly.GetExecutingAssembly().GetName().Version.ToString()); |
| // Get parameter names (null "" if no parameter). |
| int i = distribution.SelectedIndex; |
| distributionValueLabel.Text = boost_math.any_distribution.distribution_name(i).ToString(); |
| sw.WriteLine(distributionValueLabel.Text + " distribution"); |
| parameterLabel1.Text = boost_math.any_distribution.first_param_name(i).ToString(); |
| parameterLabel2.Text = boost_math.any_distribution.second_param_name(i).ToString(); |
| parameterLabel3.Text = boost_math.any_distribution.third_param_name(i).ToString(); |
| string separator = "\t "; // , or tab or space? |
| // Write parameter name & value. |
| sw.WriteLine(parameterLabel1.Text + separator + this.parameter1.Text); |
| if (boost_math.any_distribution.second_param_name(i).Length.CompareTo(0) != 0) |
| { // Is a 2nd parameter. |
| sw.WriteLine(parameterLabel2.Text + separator + this.parameter2.Text); |
| } |
| if (boost_math.any_distribution.third_param_name(i).Length.CompareTo(0) != 0) |
| { // Is a 3rd parameter. |
| sw.WriteLine(parameterLabel3.Text + separator + this.parameter3.Text); |
| } |
| sw.WriteLine(); |
| sw.WriteLine("Properties"); |
| // Show computed properties of distribution. |
| double x = double.Parse(parameter1.Text); |
| double y = double.Parse(parameter2.Text); |
| double z = double.Parse(parameter3.Text); |
| dist = new boost_math.any_distribution(i, x, y, z); |
| // Note global dist might not have been calculated yet if no of the tabs clicked. |
| try |
| { |
| mean.Text = dist.mean().ToString(); |
| } |
| catch |
| { |
| mean.Text = "Undefined"; |
| } |
| sw.WriteLine("Mean" + separator + mean.Text); |
| try |
| { |
| mode.Text = dist.mode().ToString(); |
| } |
| catch |
| { |
| mode.Text = "Undefined"; |
| } |
| sw.WriteLine("mode" + separator + mode.Text); |
| try |
| { |
| median.Text = dist.median().ToString(); |
| } |
| catch |
| { |
| median.Text = "Undefined"; |
| } |
| sw.WriteLine("Median" + separator + median.Text); |
| try |
| { |
| variance.Text = dist.variance().ToString(); |
| } |
| catch |
| { |
| variance.Text = "Undefined"; |
| } |
| sw.WriteLine("Variance" + separator + variance.Text); |
| try |
| { |
| standard_deviation.Text = dist.standard_deviation().ToString(); |
| } |
| catch |
| { |
| standard_deviation.Text = "Undefined"; |
| } |
| sw.WriteLine("Standard Deviation" + separator + standard_deviation.Text); |
| try |
| { |
| skewness.Text = dist.skewness().ToString(); |
| } |
| catch |
| { |
| skewness.Text = "Undefined"; |
| } |
| sw.WriteLine("Skewness" + separator + skewness.Text); |
| try |
| { |
| coefficient_of_variation.Text = dist.coefficient_of_variation().ToString(); |
| } |
| catch |
| { |
| coefficient_of_variation.Text = "Undefined"; |
| } |
| sw.WriteLine("Cofficient of variation" + separator + coefficient_of_variation.Text); |
| try |
| { |
| kurtosis.Text = dist.kurtosis().ToString(); |
| } |
| catch |
| { |
| kurtosis.Text = "Undefined"; |
| } |
| sw.WriteLine("Kurtosis" + separator + kurtosis.Text); |
| try |
| { |
| kurtosis_excess.Text = dist.kurtosis_excess().ToString(); |
| } |
| catch |
| { |
| kurtosis_excess.Text = "Undefined"; |
| } |
| sw.WriteLine("Kurtosis excess" + separator + kurtosis_excess.Text); |
| sw.WriteLine(); |
| |
| sw.WriteLine("Range from" + separator + dist.lowest().ToString() + separator + |
| "to" + separator + dist.uppermost().ToString()); |
| sw.WriteLine("Support from " + separator + dist.lower().ToString() +separator+ |
| "to " + separator + dist.upper().ToString()); |
| sw.WriteLine(); |
| |
| // |
| sw.WriteLine("Quantiles"); |
| if (QuantileData.Rows.Count == 1) |
| { // Add some defaults: |
| QuantileData.Rows.Add(5); // 5 Risk levels. |
| QuantileData.Rows[0].Cells[0].Value = "0.001"; // Risk values as text, |
| QuantileData.Rows[0].Cells[1].Value = dist.quantile(0.001); // & as double. |
| QuantileData.Rows[0].Cells[2].Value = dist.quantile_c(0.001); |
| QuantileData.Rows[1].Cells[0].Value = "0.01"; |
| QuantileData.Rows[1].Cells[1].Value = dist.quantile(0.01); // 99% confidence. |
| QuantileData.Rows[1].Cells[2].Value = dist.quantile_c(0.01); |
| QuantileData.Rows[2].Cells[0].Value = "0.05"; |
| QuantileData.Rows[2].Cells[1].Value = dist.quantile(0.05); |
| QuantileData.Rows[2].Cells[2].Value = dist.quantile_c(0.05); |
| QuantileData.Rows[3].Cells[0].Value = "0.1"; |
| QuantileData.Rows[3].Cells[1].Value = dist.quantile(0.1); |
| QuantileData.Rows[3].Cells[2].Value = dist.quantile_c(0.1); |
| QuantileData.Rows[4].Cells[0].Value = "0.33333333333333333"; |
| QuantileData.Rows[4].Cells[1].Value = dist.quantile(0.33333333333333333); |
| QuantileData.Rows[4].Cells[2].Value = dist.quantile_c(0.33333333333333333); |
| } |
| // else have already been calculated by entering the quantile tab. |
| for (int r = 0; r < QuantileData.Rows.Count-1; r++) |
| { // Show all the rows of quantiles, including any optional user values. |
| sw.WriteLine(QuantileData.Rows[r].Cells[0].Value.ToString() + separator + |
| QuantileData.Rows[r].Cells[1].Value.ToString() + separator + |
| QuantileData.Rows[r].Cells[2].Value.ToString()); |
| } |
| sw.WriteLine(); |
| sw.WriteLine("PDF, CDF & complement(s)"); |
| for (int r = 0; r < CDF_data.Rows.Count-1; r++) |
| { // Show all the rows of pdf, cdf, including any optional user values. |
| sw.WriteLine(CDF_data.Rows[r].Cells[0].Value.ToString() + separator + // x value. |
| CDF_data.Rows[r].Cells[1].Value.ToString() + separator + // pdf |
| CDF_data.Rows[r].Cells[2].Value.ToString() + separator + // cdf |
| CDF_data.Rows[r].Cells[3].Value.ToString());// cdf complement. |
| } |
| sw.WriteLine(); |
| } |
| |
| } // saveFileDialog1_FileOk |
| |
| private void saveToolStripMenuItem_Click(object sender, EventArgs e) |
| { |
| this.saveFileDialog.ShowDialog(); |
| } |
| |
| private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) |
| { // Same as Save. |
| this.saveFileDialog.ShowDialog(); |
| } |
| |
| private void contentsToolStripMenuItem_Click(object sender, EventArgs e) |
| { // In lieu of proper help. |
| string helpText = "\n" + AssemblyDescription + |
| "\nVersion " + Assembly.GetExecutingAssembly().GetName().Version.ToString() + |
| "\nA Windows utility to show the properties of distributions" + |
| "\n and permits calculation of probability density (or mass) function (PDF)" + |
| "\nand cumulative distribution function (CDF) and complement from values provided." + |
| "\nQuantiles are also calculated for typical risk (alpha) probabilities" + |
| "\nand for probabilities provided by the user." + |
| "\n" + |
| "\nResults can be saved to text files using Save or SaveAs." + |
| "\nAll the values on the four tabs are output to the file chosen," + |
| "\nand are tab separated to assist input to other programs," + |
| "\nfor example, spreadsheets or text editors." + |
| "\nNote: when importing to Excel only 10 decimal digits are shown by default:" + |
| "\nit is necessary to format all cells to display the full 15 decimal digits," + |
| "\nalthough not all computed values will be as accurate as this.\n" + |
| "\nValues shown as NaN cannot be calculated from the value given," + |
| "\nmost commonly because the value is outside the range for the distribution." + |
| "\n" + |
| "\nFor more information, including downloads, see " + |
| "\nhttp://sourceforge.net/projects/distexplorer/" + |
| "\n(Note that .NET framework 4.0 and VC Redistribution X86 are requirements for this program.)" + |
| "\n\nCopyright John Maddock & Paul A. Bristow 2007, 2009, 2010"; |
| |
| MessageBox.Show("Statistical Distribution Explorer\n" + helpText); |
| } |
| |
| private void newToolStripMenuItem_Click(object sender, EventArgs e) |
| { |
| MessageBox.Show("New is not yet implemented."); |
| } |
| |
| private void openToolStripMenuItem_Click(object sender, EventArgs e) |
| { |
| MessageBox.Show("Open is not yet implemented."); |
| } |
| |
| private void printToolStripMenuItem_Click(object sender, EventArgs e) |
| { |
| MessageBox.Show("Print is not yet implemented." + |
| "\nSave all values to a text file and print that file."); |
| } |
| |
| private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e) |
| { |
| MessageBox.Show("Print Preview is not yet implemented." + |
| "\nSave all values to a text file and print that file."); |
| } |
| |
| |
| |
| |
| private void exitToolStripMenuItem_Click(object sender, EventArgs e) |
| { // exit DistexForm |
| this.Close(); |
| } |
| } // class DistexForm |
| } // namespace distribution_explorer |