예제 #1
0
        public static void DrawElements(HyperbolicModel model, Vector3D[] textureCoords, Vector3D[] textureVerts, int[] elements,
                                        Isometry mouseIsometry, double textureScale)
        {
            ////////////////////// ZZZ - Use VBOs
            GL.Begin(BeginMode.Triangles);
            {
                double factor  = textureScale;
                int    skipped = 0;

                for (int i = 0; i < elements.Length; i++)
                {
                    int idx = elements[i];

                    // In Poincare model.
                    GL.TexCoord2((textureCoords[idx].X * factor + 1) / 2, (textureCoords[idx].Y * factor + 1) / 2);
                    Complex transformed = textureVerts[idx].ToComplex();
                    if (mouseIsometry != null)
                    {
                        transformed = mouseIsometry.Apply(transformed);
                    }

                    switch (model)
                    {
                    case HyperbolicModel.Poincare:
                    {
                        Vertex(transformed);
                        break;
                    }

                    case HyperbolicModel.Klein:
                    {
                        Vector3D temp = Vector3D.FromComplex(transformed);
                        Vertex(PoincareToKlein(temp));
                        break;
                    }

                    case HyperbolicModel.Pseudosphere:
                    {
                        Mobius m = new Mobius();
                        m.UpperHalfPlane();
                        Complex u   = m.Apply(transformed);
                        double  x   = u.Real;
                        double  y   = u.Imaginary;
                        double  max = 1 * System.Math.PI;
                        double  min = -1 * System.Math.PI;
                        if (0 == i % 3 && (x < min - 1 || x > max + 1 || y < 0))
                        {
                            skipped = 1;
                            continue;
                        }

                        if (skipped > 0 && skipped < 3)
                        {
                            skipped++;
                            continue;
                        }

                        skipped = 0;

                        GL.TexCoord2((textureCoords[idx].X * factor + 1) / 2, (textureCoords[idx].Y * factor + 1) / 2);

                        // Pseudosphere
                        Func <double, Complex> tractrix = new Func <double, Complex>(
                            (t) =>
                            {
                                return(new Complex(t - Math.Tanh(t), 1.0 / Math.Cosh(t)));
                            });

                        //Vector3D temp1 = Vector3D.FromComplex( u );
                        if (x < min)
                        {
                            x = min;
                        }
                        if (x > max)
                        {
                            x = max;
                        }
                        if (y < 1)
                        {
                            y = 1;
                        }
                        Vector3D temp1 = new Vector3D(x, y);

                        double   logy  = Math.Log(temp1.Y);
                        Complex  tract = tractrix(logy);
                        Vector3D temp2 = new Vector3D(
                            Math.Cos(temp1.X) * tract.Imaginary,
                            Math.Sin(temp1.X) * tract.Imaginary,
                            tract.Real);

                        GL.Vertex3(temp2.X, temp2.Y, temp2.Z);

                        //temp1 = m.Inverse().Apply( temp1 );
                        //GL.Vertex3( temp1.X, temp1.Y, temp1.Z );
                        //Vertex( temp1 );

                        break;
                    }

                    case HyperbolicModel.Hyperboloid:
                    {
                        Vector3D hyper = Sterographic.PlaneToHyperboloid(Vector3D.FromComplex(transformed));                                                    // Hyperboloid
                        GL.Vertex3(hyper.X, hyper.Y, hyper.Z);
                        break;
                    }

                    default:
                    {
                        System.Diagnostics.Debug.Assert(false);
                        break;
                    }
                    }

                    /* // PETALS
                     * int petals = 7;
                     * double newMag = transformed.Magnitude * ( 1 + 0.5 * Math.Sin( transformed.Phase * petals ) );
                     * double newPhase = transformed.Phase + ( -0.2 * newMag * Math.Pow( Math.Sin( newMag * 3 ), 1 ) * Math.Cos( transformed.Phase * petals ) );
                     * transformed = Complex.FromPolarCoordinates( newMag, newPhase );
                     *
                     * Vertex( transformed );
                     * */

                    //double mag = System.Math.Pow( transformed.Magnitude, 3 ) / transformed.Magnitude;				// nice
                    //double mag = System.Math.Pow( transformed.Magnitude - 3, 2 ) + .0;							// looks spherical

                    //double mag = transformed.Magnitude + 0.1* System.Math.Sin( transformed.Magnitude * 15 );		// Fun warping (20 is cool too)
                    //Vertex( transformed * mag );

                    /*double xmag = 1;
                     * double ymag = transformed.Imaginary + 0.1 * System.Math.Sin( transformed.Imaginary * 15 );
                     * xmag = System.Math.Abs( xmag );
                     * ymag = System.Math.Abs( ymag );
                     * Vertex( new Complex( transformed.Real * xmag, transformed.Imaginary * ymag ) );	*/

                    //Vertex( 2 / System.Math.PI * Complex.Log( ( 1 + transformed ) / ( 1 - transformed ) ) );		// Band model
                    //Vertex( Complex.Pow( transformed, 3 ) / transformed.Magnitude );								// Spikey

                    // Spiral
                    //Complex band = 2 / System.Math.PI * Complex.Log( ( 1 + transformed ) / ( 1 - transformed ) );
                    //band = new Complex( band.Real, band.Imaginary + 0.3 * System.Math.Sin( band.Real * 2 ) );
                    //band = new Complex( band.Real * .5, band.Imaginary );
                    //band += new Complex( 0, .5 );
                    //Vertex( band );

                    /*
                     * double x = band.Real;
                     * double y = band.Imaginary;
                     *
                     * double r = System.Math.Exp( x );
                     * double theta = 3*( x + y/1.75 ); */
                    //Vertex( new Complex( r * System.Math.Sin( theta ), r * System.Math.Cos( theta ) ) );			// Spiral
                }
            }
            GL.End();
        }
        private async void CalculateScores()
        {
            List <double> xRange = mWindow.ParseRange(Delays);
            List <double> yRange = mWindow.ParseRange(Values);

            if (!double.TryParse(MaxValue, out maxValueA) || (xRange.Count != yRange.Count))
            {
                mInterface.SendMessageToOutput("Error in computing ranges, inputs must be equal in length.");
                mInterface.SendMessageToOutput("Counts for Delays and Values were " + xRange.Count + " and " + yRange.Count + " respectively.");
                mInterface.SendMessageToOutput("Max value was: " + maxValueA);
                MessageBox.Show("Hmm, check your ranges.  These don't seem paired up");
                return;
            }

            mInterface.SendMessageToOutput("---------------------------------------------------");

            mDiscount.maxValue = maxValueA;
            mDiscount.xArray   = xRange;
            mDiscount.yArray   = yRange;

            mInterface.SendMessageToOutput("Results of Johnson & Bickel criteria: " + mDiscount.getJohnsonBickelCriteria());

            var   chartWin = new ChartingWindow();
            Chart chart    = chartWin.FindName("MyWinformChart") as Chart;

            chart.Series.Clear();
            // Style chart areas
            chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
            chart.ChartAreas[0].AxisX.Minimum           = 0;
            chart.ChartAreas[0].AxisX.Title             = "Delays";
            chart.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
            chart.ChartAreas[0].AxisY.Minimum           = 0;
            chart.ChartAreas[0].AxisY.Title             = "Values";

            int seriesCount = 0;

            if (runAUC)
            {
                mInterface.SendMessageToOutput("---------------------------------------------------");
                mInterface.SendMessageToOutput("Calculating Area Under Curve...");

                double AUC = await GetAreaUnderCurve();

                mInterface.SendMessageToOutput("Results of AUC were " + AUC.ToString("0.0000"));

                var series = new Series
                {
                    Name              = "AUC",
                    Color             = System.Drawing.Color.Blue,
                    IsVisibleInLegend = true,
                    IsXValueIndexed   = false,
                    ChartType         = SeriesChartType.Point
                };

                chart.Series.Add(series);

                for (int i = 0; i < xRange.Count; i++)
                {
                    chart.Series[seriesCount].Points.AddXY(xRange[i], yRange[i]);
                }

                chart.Legends.Add(series.Name);

                seriesCount++;
            }
            if (runExp)
            {
                mInterface.SendMessageToOutput("---------------------------------------------------");
                mInterface.SendMessageToOutput("Fitting Exponential Model...");

                double kVal = 0;

                try
                {
                    NumericVector delays = engine.CreateNumericVector(xRange.ToArray());
                    engine.SetSymbol("delays", delays);

                    NumericVector values = engine.CreateNumericVector(yRange.ToArray());
                    engine.SetSymbol("values", values);

                    GenericVector testResult = engine.Evaluate("nls(values ~ " + maxValueA + " * exp(-a*delays), start = list(a = 0))").AsList();

                    engine.SetSymbol("exponentialModel", testResult);
                    kVal = engine.Evaluate("coef(exponentialModel)").AsNumeric().First();
                }
                catch (EvaluationException evalExc)
                {
                    System.Console.WriteLine(evalExc.ToString());
                    mInterface.SendMessageToOutput("R methods failed to achieve convergence.  Defaulting to SnS backups...");

                    /*
                     *  Fall-back method if convergence issues found
                     */

                    ExponentialModel exponentialModel = await GetExponentialModel();

                    kVal = exponentialModel.Constant;
                }

                double exponentialED50 = mDiscount.getExponentialED50(kVal);

                double expR2 = mDiscount.getExponentialR2(kVal);

                mInterface.SendMessageToOutput("Results of Exponential fit were k: " + kVal.ToString("0.0000") + ", r2: " + expR2.ToString("0.0000"));
                mInterface.SendMessageToOutput("Results of exponential ED50: " + exponentialED50.ToString("0.0000"));

                var series = new Series
                {
                    Name              = "Exponential Model",
                    Color             = System.Drawing.Color.Purple,
                    IsVisibleInLegend = true,
                    IsXValueIndexed   = false,
                    ChartType         = SeriesChartType.Line
                };

                chart.Series.Add(series);

                double projected;

                for (int i = (int)xRange[0]; i < xRange[xRange.Count - 1]; i++)
                {
                    projected = maxValueA * System.Math.Exp(-kVal * i);

                    chart.Series[seriesCount].Points.AddXY(i, projected);
                }

                chart.Legends.Add(series.Name);

                seriesCount++;
            }
            if (runHyp)
            {
                mInterface.SendMessageToOutput("---------------------------------------------------");
                mInterface.SendMessageToOutput("Fitting hyperbolic Model...");

                double kVal = 0;

                try
                {
                    NumericVector delays = engine.CreateNumericVector(xRange.ToArray());
                    engine.SetSymbol("delays", delays);

                    NumericVector values = engine.CreateNumericVector(yRange.ToArray());
                    engine.SetSymbol("values", values);

                    GenericVector testResult = engine.Evaluate("nls(values ~ " + maxValueA + " / (1 + a*delays), start = list(a = 0))").AsList();
                    engine.SetSymbol("hyperbolicModel", testResult);
                    kVal = engine.Evaluate("coef(hyperbolicModel)").AsNumeric().First();
                }
                catch (EvaluationException evalExc)
                {
                    /*
                     *  Fall-back method if convergence issues found
                     */

                    System.Console.WriteLine(evalExc.ToString());
                    mInterface.SendMessageToOutput("R methods failed to achieve convergence.  Defaulting to SnS backups...");

                    HyperbolicModel hyperbolicModel = await GetHyperbolicModel();

                    kVal = hyperbolicModel.Constant;
                }

                double hyperbolicED50 = mDiscount.getAinslieED50(kVal);

                double hypR2 = mDiscount.getHyperbolicR2(kVal);

                mInterface.SendMessageToOutput("Results of hyperbolic fit were k: " + kVal.ToString("0.0000") + ", r2: " + hypR2.ToString("0.0000"));
                mInterface.SendMessageToOutput("Results of hyperbolic ED50: " + hyperbolicED50.ToString("0.0000"));

                var series = new Series
                {
                    Name              = "Hyperbolic Model",
                    Color             = System.Drawing.Color.LimeGreen,
                    IsVisibleInLegend = true,
                    IsXValueIndexed   = false,
                    ChartType         = SeriesChartType.Line
                };

                chart.Series.Add(series);

                double projected;

                for (int i = (int)xRange[0]; i < xRange[xRange.Count - 1]; i++)
                {
                    projected = maxValueA / (1 + kVal * i);
                    chart.Series[seriesCount].Points.AddXY(i, projected);
                }

                chart.Legends.Add(series.Name);

                seriesCount++;
            }
            if (runQuasi)
            {
                mInterface.SendMessageToOutput("---------------------------------------------------");
                mInterface.SendMessageToOutput("Fitting quasi-hyperbolic Model...");

                double[] kVal = new double[2];

                try
                {
                    NumericVector delays = engine.CreateNumericVector(xRange.ToArray());
                    engine.SetSymbol("delays", delays);

                    NumericVector values = engine.CreateNumericVector(yRange.ToArray());
                    engine.SetSymbol("values", values);

                    GenericVector testResult = engine.Evaluate("nls(values ~ " + maxValueA + " * a * exp(-b*delays), start = list(a = 0.5, b = 0.001))").AsList();

                    engine.SetSymbol("quasiModel", testResult);
                    kVal = engine.Evaluate("coef(quasiModel)").AsNumeric().ToArray();
                }
                catch (EvaluationException evalExc)
                {
                    System.Console.WriteLine(evalExc.ToString());

                    mInterface.SendMessageToOutput("R methods failed to achieve convergence.  Defaulting to SnS backups...");

                    /*
                     * Backup methods
                     */

                    QuasiHyperbolicModel quasiHyperbolicModel = await GetQuasiHyperbolicModel();

                    kVal = new double[] { quasiHyperbolicModel.Beta, quasiHyperbolicModel.Constant };
                }

                double quasiED50 = mDiscount.getQuasiED50(kVal[0], kVal[1], maxValueA);

                double quasiR2 = mDiscount.getQuasiHyperbolicR2(kVal[0], kVal[1]);

                mInterface.SendMessageToOutput("Results of quasi-hyperbolic fit were beta: " + kVal[0].ToString("0.0000") + " k: " + kVal[1].ToString("0.0000") + ", r2: " + quasiR2.ToString("0.0000"));
                mInterface.SendMessageToOutput("Results of quasi-hyperbolic ED50: " + quasiED50.ToString("0.0000"));

                var series = new Series
                {
                    Name              = "Quasi-Hyperbolic Model",
                    Color             = System.Drawing.Color.Magenta,
                    IsVisibleInLegend = true,
                    IsXValueIndexed   = false,
                    ChartType         = SeriesChartType.Line
                };

                chart.Series.Add(series);

                double projected;

                for (int i = (int)xRange[0]; i < xRange[xRange.Count - 1]; i++)
                {
                    projected = maxValueA * kVal[0] * System.Math.Exp(-kVal[1] * i);
                    chart.Series[seriesCount].Points.AddXY(i, projected);
                }

                chart.Legends.Add(series.Name);

                seriesCount++;
            }
            if (runMyerson)
            {
                mInterface.SendMessageToOutput("---------------------------------------------------");
                mInterface.SendMessageToOutput("Fitting hyperboloid (Myerson's) Model...");

                double[] kVal = new double[2];

                try
                {
                    NumericVector delays = engine.CreateNumericVector(xRange.ToArray());
                    engine.SetSymbol("delays", delays);

                    NumericVector values = engine.CreateNumericVector(yRange.ToArray());
                    engine.SetSymbol("values", values);

                    GenericVector testResult = engine.Evaluate("nls(values ~ " + maxValueA + " / ((1 + a*delays)^b), start = list(a = 0.001, b = 0.2))").AsList();

                    engine.SetSymbol("myersonModel", testResult);
                    kVal = engine.Evaluate("coef(myersonModel)").AsNumeric().ToArray();
                }
                catch (EvaluationException evalExc)
                {
                    System.Console.WriteLine(evalExc.ToString());
                    mInterface.SendMessageToOutput("R methods failed to achieve convergence.  Defaulting to SnS backups...");

                    /*
                     * Backup methods
                     */

                    HyperboloidMyersonModel hyperboloidModelMyerson = mDiscount.GetHyperboloidMyerson();
                    kVal = new double[] { hyperboloidModelMyerson.Constant, hyperboloidModelMyerson.Scaling };
                }

                double hyperboloidMyersonED50 = mDiscount.getMyersonED50(kVal[0], kVal[1]);

                double myersonR2 = mDiscount.getHyperboloidMyersonR2(kVal[0], kVal[1]);

                mInterface.SendMessageToOutput("Results of hyperboloid fit (Myerson) were k: " + kVal[0].ToString("0.0000") + " s: " + kVal[1].ToString("0.0000") + ", r2: " + myersonR2.ToString("0.0000"));
                mInterface.SendMessageToOutput("Results of hyperboloid (Myerson) ED50: " + hyperboloidMyersonED50.ToString("0.0000"));

                var series = new Series
                {
                    Name              = "Hyperboloid (M) Model",
                    Color             = System.Drawing.Color.DarkCyan,
                    IsVisibleInLegend = true,
                    IsXValueIndexed   = false,
                    ChartType         = SeriesChartType.Line
                };

                chart.Series.Add(series);

                double projected;

                for (int i = (int)xRange[0]; i < xRange[xRange.Count - 1]; i++)
                {
                    projected = mDiscount.LookupWithS(kVal[0], maxValueA, i, kVal[1]);
                    chart.Series[seriesCount].Points.AddXY(i, projected);
                }

                chart.Legends.Add(series.Name);

                seriesCount++;
            }
            if (runRachlin)
            {
                mInterface.SendMessageToOutput("---------------------------------------------------");
                mInterface.SendMessageToOutput("Fitting hyperboloid (Rachlin's) Model...");

                /*
                 * Nuke after verifying with R
                 */

                double[] kVal = new double[2];

                try
                {
                    NumericVector delays = engine.CreateNumericVector(xRange.ToArray());
                    engine.SetSymbol("delays", delays);

                    NumericVector values = engine.CreateNumericVector(yRange.ToArray());
                    engine.SetSymbol("values", values);

                    GenericVector mod = engine.Evaluate("nls.control(maxiter = 1000)").AsList();

                    GenericVector testResult = engine.Evaluate("nls(values ~ " + maxValueA + " / (1 + (a*delays)^b), start = list(a = 0.001, b = 0.2))").AsList();

                    engine.SetSymbol("rachlinModel", testResult);

                    kVal = engine.Evaluate("coef(rachlinModel)").AsNumeric().ToArray();
                }
                catch (EvaluationException evalExc)
                {
                    System.Console.WriteLine(evalExc.ToString());
                    mInterface.SendMessageToOutput("R methods failed to achieve convergence.  Defaulting to SnS backups...");

                    /*
                     * Backup methods
                     */

                    HyperboloidRachlinModel hyperboloidModelRachlin = await GetHyperboloidRachlin();

                    kVal = new double[] { hyperboloidModelRachlin.Constant, hyperboloidModelRachlin.Scaling };
                }

                double hyperboloidRachlinED50 = mDiscount.getRachlinED50(kVal[0], kVal[1], maxValueA);

                double rachlinR2 = mDiscount.getHyperboloidRachlinR2(kVal[0], kVal[1]);

                mInterface.SendMessageToOutput("Results of hyperboloid fit (Rachlin) were k: " + kVal[0].ToString("0.0000") + " s: " + kVal[1].ToString("0.0000") + ", r2: " + rachlinR2.ToString("0.0000"));
                mInterface.SendMessageToOutput("Results of hyperboloid (Rachlin) ED50: " + hyperboloidRachlinED50.ToString("0.0000"));

                var series = new Series
                {
                    Name              = "Hyperboloid (R) Model",
                    Color             = System.Drawing.Color.Crimson,
                    IsVisibleInLegend = true,
                    IsXValueIndexed   = false,
                    ChartType         = SeriesChartType.Line
                };

                chart.Series.Add(series);

                double projected;

                for (int i = (int)xRange[0]; i < xRange[xRange.Count - 1]; i++)
                {
                    projected = mDiscount.lookUpWithSInside(kVal[0], maxValueA, i, kVal[1]);
                    chart.Series[seriesCount].Points.AddXY(i, projected);
                }

                chart.Legends.Add(series.Name);

                seriesCount++;
            }

            chart.Legends[0].IsDockedInsideChartArea = true;
            chartWin.Owner = windowRef;
            chartWin.Show();
        }