0

I have searched through many posts and cannot find what I need. I see solutions to find the closest number to a target but I need one that finds that number, then can select the closest number on the other side of a "parabola" shaped set of data that is not completely symmetrical. I essentially use:

List<int> list = new List<int> { 2, 5, 7, 10 };
int number = 9;

int closest = list.Aggregate((x,y) => Math.Abs(x-number) < Math.Abs(y-
number) ? x : y);

This is how I find my first target number. Now I need to find a second number that is almost equal in value but on the other side of a parabola (I really need the indexes of these numbers but I can put the pieces together). My methods keeps coming up a single number. Essentially I need to move to an approximately symmetric index across a parabola to select an equivalent number. To put this in context, I am calculating beam width, i.e. the distance between the sides of a parabola at a specific point. Please let me know if this makes sense and if I need to explain more before you down vote me. I have done extensive research and testing. It is difficult for me to provide more code because it is coming from a $500,000 testing system that does not have internet so I can't copy and paste my code. I can go the extra yard if more code is needed though, just trying to avoid compromising an expensive embedded Windows system.

Here is a related post that I need to go a step further from located here

Edit adding full code:

fileName = textBox10.Text;
            SetupControlState(true);


            if (comboBox2.SelectedIndex == 0)
            {
                cent = false;
            }
            else if (comboBox2.SelectedIndex == 1)
            {
                cent = true;
            }
           testHPositions = new List<double>();
           testHMeasurements = new List<double>();

            testVPositions = new List<double>();
            testVMeasurements = new List<double>();

            double horzRange = Double.Parse(textBox12.Text);
            double vertRange = Double.Parse(textBox11.Text);
            double refGain = Double.Parse(textBox14.Text);
            double stepSize = Double.Parse(textBox13.Text);
            testBorePos = new double[1, 2];
            _worker = new BackgroundWorker();
            _worker.WorkerSupportsCancellation = true;

            testBoreRun.Enabled = false;
            button2.Enabled = true;
            _worker.RunWorkerAsync();

            _worker.DoWork += new DoWorkEventHandler((state, args) =>
            {
                //  try
                // {
                dev1 = new VisaDevice("inst0", "TCPIP0::192.168.0.10::inst0::INSTR"); //textBox1.Text);
                if (!cent)
                {
                    Double startfreq = double.Parse(textBox2.Text) * 1000000000;
                    Double stopfreq = double.Parse(textBox1.Text) * 1000000000;

                    dev1.SendBlocking("FREQ:STAR " + startfreq.ToString(), true);
                    string responseFreq = "";
                    dev1.QueryBlocking("FREQ:STAR?", ref responseFreq, true);
                    dev1.SendBlocking("FREQ:STOP " + stopfreq.ToString(), true);

                    dev1.QueryBlocking("FREQ:STOP?", ref responseFreq, true);
                }

                else if (cent)
                {
                    Double freq = double.Parse(textBox9.Text) * 1000000000;
                    Double span = double.Parse(textBox8.Text) * 1000000000;
                    dev1.SendBlocking("FREQ:CENT " + freq.ToString(), true);
                    string responseFreq = "";
                    dev1.QueryBlocking("FREQ:CENT?", ref responseFreq, true);
                    dev1.SendBlocking("FREQ:SPAN " + span.ToString(), true);
                    dev1.QueryBlocking("FREQ:SPAN?", ref responseFreq, true);
                    //   this.InvokeEx(f => f.stringReadTextBox.AppendText("Spectrum Analyzer Connected" + Environment.NewLine));
                }
                string progID;
                Util U = new Util();
                progID = "ASCOM.iOptron.Telescope";
                if (progID != "")
                {
                    PauseClass pause;
                    pause = new PauseClass();
                    Telescope T = new Telescope(progID);
                    T.Connected = true;
                    pause.Pause(5000);
                    T.Tracking = false;
                    T.TargetDeclination = 1;
                    T.TargetRightAscension = 1;
                    this.InvokeEx(f => f.stringReadTextBox.AppendText("  Connected to " + progID + Environment.NewLine));
                    this.InvokeEx(f => f.stringReadTextBox.AppendText("  Connected to Spectrum Analyzer" + Environment.NewLine));

                    T.SlewToAltAz(180.00, 45 - vertRange);
                    double Alt = T.Altitude;
                    for (int i = 0; i < ((vertRange * 2) / stepSize) + 1; i++)
                    {
                        if (_worker.CancellationPending)
                            break;

                        T.SlewToAltAz(180, Alt + stepSize * i);
                        this.InvokeEx(f => f.stringReadTextBox.AppendText("Test Altitude = " +(T.Altitude - 45).ToString("F") + Environment.NewLine));
                        testVPositions.Add(T.Altitude);
                        dev1.SendBlocking("INIT", true); //Start single measurement

                        string respOPC = "", responseState = "", responseMarkerY = "";
                        dev1.QueryBlocking("*OPC?", ref respOPC, true); //Wait for operation complete
                        dev1.QueryBlocking("STAT:QUES:MEAS?", ref responseState, true); //Check State
                        dev1.QueryBlocking("CALC:MARK:Y?", ref responseMarkerY, true); // Get the result
                        this.InvokeEx(f => f.stringReadTextBox.AppendText(responseMarkerY + Environment.NewLine));
                        testVMeasurements.Add(Double.Parse(responseMarkerY));

                        if (testVMeasurements.Count > ((vertRange * 2) / stepSize))
                        {


                            this.InvokeEx(f => f.stringReadTextBox.AppendText("Vertical Scanning Is Complete!" + Environment.NewLine));

                            double maxVamp = testVMeasurements.Max();
                            int index2 = testVMeasurements.IndexOf(testVMeasurements.Max());
                            double maxVPos = testVPositions[index2];
                            testBorePos[0, 1] = maxVPos;
                            this.InvokeEx(f => f.stringReadTextBox.AppendText("Vertical Max Amplitude = " + maxVamp + Environment.NewLine));
                            this.InvokeEx(f => f.stringReadTextBox.AppendText("Vertical Position of  Max Amplitude = " + (maxVPos - 45).ToString("F") + Environment.NewLine));



                        }
                    }

                    if (!_worker.CancellationPending)
                    {
                        T.SlewToAltAz(180.00 - horzRange, testBorePos[0, 1]);
                    }

                    double Az = T.Azimuth;
                    for (int i = 0; i < ((horzRange * 2) / stepSize) + 1; i++)
                    {
                        if (_worker.CancellationPending)
                            break;
                        if (vertRange > 20)
                        {

                            this.InvokeEx(f => f.stringReadTextBox.AppendText("Vertical Range Cannot Be Greater than +/- 20 Degreez" + Environment.NewLine));
                            break;
            }
                        T.SlewToAltAz(Az + stepSize * i,testBorePos[0,1]);

                        this.InvokeEx(f => f.stringReadTextBox.AppendText("Test Azimuth = " + (T.Azimuth-180).ToString("F") + Environment.NewLine));

                        testHPositions.Add(T.Azimuth);
                        dev1.SendBlocking("INIT", true); //Start single measurement
                        string respOPC = "", responseState = "", responseMarkerY = "", responseMarkerX = "";
                        // string responseFreq = "";
                        dev1.QueryBlocking("*OPC?", ref respOPC, true); //Wait for operation complete
                        dev1.QueryBlocking("STAT:QUES:MEAS?", ref responseState, true); //Check State
                        dev1.QueryBlocking("CALC:MARK:Y?", ref responseMarkerY, true); // Get the result
                        dev1.QueryBlocking("CALC:MARK:X?", ref responseMarkerX, true); // Get the result
                        this.InvokeEx(f => f.stringReadTextBox.AppendText(responseMarkerY + Environment.NewLine));
                        testHMeasurements.Add(Double.Parse(responseMarkerY));

                        if (testHMeasurements.Count > ((horzRange * 2) / stepSize))
                        {
                            _worker.CancelAsync();
                            stop = false;
                            this.InvokeEx(f => f.testBoreRun.Enabled = true);
                            this.InvokeEx(f => f.button2.Enabled = false);
                            this.InvokeEx(f => f.stringReadTextBox.AppendText("Horizontal Scanning Is Complete!" + Environment.NewLine));
                            double maxHamp =testHMeasurements.Max();
                            int index =testHMeasurements.IndexOf(testHMeasurements.Max());
                            double maxHPos =testHPositions[index];
                            testBorePos[0, 0] = maxHPos;
                            this.InvokeEx(f => f.stringReadTextBox.AppendText("Horizontal Max Amplitude = " + maxHamp + Environment.NewLine));
                            this.InvokeEx(f => f.stringReadTextBox.AppendText("Horizontal Position of  Max Amplitude = " +( maxHPos-180).ToString("F") + Environment.NewLine));
                            this.InvokeEx(f => f.stringReadTextBox.AppendText("Antenna Under Test Peak Amplitude located at (" + (testBorePos[0, 0] - 180).ToString("F") + " , " + (testBorePos[0, 1] - 45).ToString("F") + ")" + Environment.NewLine));
                            this.InvokeEx(f => f.SetupControlState(false));

                            T.SlewToAltAz(testBorePos[0, 0], testBorePos[0, 1]);
                            dev1.SendBlocking("INIT", true); //Start single measurement
                            maxAmpTest = new double();
                            string respOPC2 = "", responseState2 = "", responseMarkerY2 = "";
                            dev1.QueryBlocking("*OPC?", ref respOPC2, true); //Wait for operation complete
                            dev1.QueryBlocking("STAT:QUES:MEAS?", ref responseState2, true); //Check State
                            dev1.QueryBlocking("CALC:MARK:Y?", ref responseMarkerY2, true); // Get the result
                            maxAmpTest = Double.Parse(responseMarkerY2);
                            double target = maxAmpTest - 3;

Here is where I am stuck:

                            //    int indexbeam = testHMeasurements.IndexOf(target);
                            // indexList = testHMeasurements.IndexOf(testHMeasurements.FindAll(s => s.Equals(target)).First());
                            double closest = testHMeasurements.Aggregate((x, y) => Math.Abs(x - target) < Math.Abs(y - target) ? x : y);
                            var result = Enumerable.Range(0, testHMeasurements.Count).Where(j => testHMeasurements[j] ==closest).ToList();
                         // int beamIndex1 = testHMeasurements.IndexOf(testHMeasurements.OrderBy(item => Math.Abs(target - item)).First());
                          //  int beamIndex2 = testHMeasurements.IndexOf(testHMeasurements.OrderBy(item => Math.Abs((beamIndex1 + 1) - item)).First());
                            double beam1 =( testHPositions[result[0]]) - 180;
                            double beam2 = (testHPositions[result[1]]) - 180;
                            beamWidth = Math.Abs(beam1) + Math.Abs(beam2);

                            this.InvokeEx(f => f.stringReadTextBox.AppendText("Antenna Under Test Amplitude = " + responseMarkerY2 + Environment.NewLine));
                            this.InvokeEx(f => f.stringReadTextBox.AppendText(" Antenna Under Test Gain = " + (maxAmpTest - refAmp + refGain) + Environment.NewLine));
                            this.InvokeEx(f => f.stringReadTextBox.AppendText(" Antenna Under Test Beam Width = " +beamWidth.ToString("F") + Environment.NewLine));
                            testGain = maxAmpTest - refAmp + refGain;
                        }


                    }

                    T.Connected = false;
                    T.Dispose();
                    dev1.Dispose();
                    if (_worker.CancellationPending)
                    {
                        Save();

                        // Cleanup Excel resources
                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                    }
                }
            });
Community
  • 1
  • 1
Harrison
  • 57
  • 11
  • If first number is 9 , is not the second one -9? Or did I understand something not correct? – Samvel Petrosov May 16 '17 at 17:08
  • 2
    I don't see any programming question here yet. "distance between the sides of a parabola at a specific point" is basic math... As @S.Petrosov said for basic y=x*x case you don't even need to do any calculations and {-x,y} is the other point ... – Alexei Levenkov May 16 '17 at 17:17
  • I do not understand how your parabola is defined. If the list index is `x` and the list content is `y`, then the given numbers define a kind of `s`, not a parabola. Is the parabola supposed to be symmetric to x = 0? – Olivier Jacot-Descombes May 16 '17 at 17:17
  • my parabola is not defined by the above code, that is simply indexing code pulled from a similar question. Just picture a parabola which the above code selects a y coordinate of. I need to find both x coordinates related to the calculated y coordinate. All of the parabola coordinates are contained in two separate lists. The parabola is not exactly symmetric is the problem. I apologize for not providing a clear question it is quite complicated to explain the error in my code. Please give me a chance to clarify before down voting I hardly have any rep and struggle to build it. – Harrison May 16 '17 at 17:38
  • my parabola is created by scanning a range of positions and taking measurements at each position, due to the physics of radar antennas generating the data, it creates a parabola if you plot the position versus the measurement (power level). I need to find the distance (delta x) between each side of the "parabola" for a given y coordinate which is calculated as "closest" in the above code. I will connect the system to the internet and show the full code in a minute so I am not downvoted more.... – Harrison May 16 '17 at 17:43
  • see updates: parabola is not symmetric ( i.e. not actually a parabola but extremely similar and shape) – Harrison May 16 '17 at 18:01
  • I need to carry out this function twice: var result = Enumerable.Range(0,testHMeasurements.Count).Where(j => testHMeasurements[j] ==closest).ToList(); It is only selecting one number I need it to select 2 – Harrison May 16 '17 at 18:06

2 Answers2

2

First, you must find the parabola. Because your data only approximates the parabola, you need a statistical method called Quadratic Regression, or Polynomial Regression to find the parameters a, b and c of the equation

y = ax2 + bx + c

defining the parabola, that best fits the dataset given by the points

(xi, yi)

Use a math library or google for an algorithm.

Once you have the parabola, determine the symmetry axis of it, i.e. find the x-value of where the minimum or maximum (if the parabola is upside down) of the parabola is.

xs = -b / 2a

Now, once you have a given x-value, you can find a point at the opposite side of the parabola by mirroring x at xs

x' = 2xs - x

This is the explanation for a parabola in 2-D. If you have a parabola in 3-D, i.e. a Paraboloid the principle remains the same, but with more complex math. Google for Paraboloid Regression. A parabolic antenna has a curved surface with the cross-sectional shape of a parabola, called a paraboloid in geometrical terms.

Only once you have solved the mathematical problems, you can start programming and finding points in lists.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • Thank you very much! I will start implementing a regression method. I may need more help so please check back. Do you know of any C# functions or libraries that have the ability to do this? – Harrison May 17 '17 at 13:24
  • I don't, but you can start to search Stack Overflow: http://stackoverflow.com/search?q=quadratic+regression+%5Bc%23%5D – Olivier Jacot-Descombes May 17 '17 at 13:27
  • thank you, if you don't mind, please throw me an up vote as the down vote police got to me before I could add the full code (it came off a half million dollar system as mentioned so I couldn't easily upload). I really need the rep to be able to leave comments on other posts to ask questions – Harrison May 18 '17 at 14:34
  • Your question has been downvoted because of different reasons. It is more of a math question than a programming question. You are talking about a parabola, but it is not clear, how the parabola is represented in your code. You are showing a lot of code irrelevant to this parabola question. See [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask) and [How to Ask a Question on Stack Overflow](http://www.wikihow.com/Ask-a-Question-on-Stack-Overflow) – Olivier Jacot-Descombes May 18 '17 at 20:51
  • I thought it was a programming question due to needing a complex method of indexing to potentially solve it. I added extra code after it was down voted to show that I am putting in effort. The parabola (more of a parabolic shaped arc) is represented by position measurements plotted against signal analyzer power measurements – Harrison May 18 '17 at 21:19
  • the parabola is the described data set which I then output to excel and plot to actually show the parabola – Harrison May 18 '17 at 21:20
0

Turns out this question could actually be solved through programming with no advanced math required. Given a y-value and asked to find two corresponding x values on an asymmetrical/parabola arc you can simply split the arc at the vertex in two pieces then scan each of the two arrays for the matching x-value. It works like a charm - just requires a little critical thinking and a lot less over thinking it (math major stuff :p)

Harrison
  • 57
  • 11
  • You can still use the calculated x-value to perform a binary search in the array, if the coordinates are in sequence. A simple scan has a cost of O(n), a binary search a cost of O(log(n)). – Olivier Jacot-Descombes Aug 16 '17 at 12:00