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(); }