Javascript  

 

 

 

 

 

Plot Constellation

 

this code is created first by chatGPT on Jan 27 2023 (meaning using chatGPT 3.5) and then modified a little bit my me. The initial request that I put into chatGPT is as follows :

 

Write a javascript with the following requirement

1. Use math.js library for math operations and assume that math.js file is located at mathjs/math.js

2. create a table at the center of the page. Gridlines of the table should be visible and thin.

3. the table has three rows and one column, make grid visible in thin line

4. In the first cell, put a textbox that can take in a number named as 'NoOfSample', the title of this text box is 'Number of samples' and a button named as 'Constellation'. the default value of the text box is 600.

5. In the second cell, put a textbox that can take in a number named as 'Noise'. Title of this text box is 'Gaussian Noise (in dB)' .the default value of the text box is -15.

6. In the third cell, put a canvas that plot the data in the file in the lower row. Do not put any background in the canvas. the background should be all white.

7. set the range of the canvas so that x axis range is '-2 <= x <= 2' and y axis range is '-2 <= x <= 2'. Use scale and translation method of canvas for this.

8. make the edge of the canvas visible

9. plot axis lines at (0,0) in the plot in black

10. plot a grid lines in the plot in gray. Grid lines should start from x axis and y axis

11. Generate an array of random complex numbers with real part to be -1 or 1 and imaginary part to be -1 or 1. Both real and imaginary number is added with gaussian noise spcified at step 5.  The name of array is 'Signal'

12. Plot the complex array 'Signal' on the canvas when 'Constellation' button is clicked. Real part of the complex number should be x coordinate and Imaginary part of the complex number should be y coordinate

13. javascript for the plot should be stored in a separate file

14. do not use css.

15. Create an html file that combines all of these components

NOTE : It is not guaranteed that you would have the same code as I got since chatGPT produce the answers differently depending on the context. And it may produce the different answers everytime you ask even with the exact the same question.

NOTE : I noticed that chatGPT misses some of the requirement or misinterprets. The part highlighted in red are the parts that are missed or misinterpreted. In many case, chatGPT generated real number random data instead of complex number and uniform random number instead of gaussian noise. But if you ask again with the specific requirement (e.g, you should add gaussian noise instead of uniform noise etc), then chatGPT would fix it.

NOTE : If you don't have any of your own idea for the request, copy my request and paste it into the chatGPT and put additional requests based on the output for the previous request. I would suggest to create a new thread in the chatGPT and put my request and then continue to add your own request.

 

Usage : Click on [Constellation] button. Whenever you click on it, you will get different constellation.

 

 

Constellation.html

<!DOCTYPE html>

<html>

 

<head>

    <title>Constellation Plot</title>

 

</head>

 

<body>

    <table align="center" style="border-collapse: collapse; border: 1px solid black;">

        <tr>

            <td>

                <label for="NoOfSample">Number of samples</label>

                <input type="number" id="NoOfSample" name="NoOfSample" value="600" min="1">

                <button id="Constellation" onClick="plotSignal()">Constellation</button>

            </td>

        </tr>

        <tr>

            <td>

                <label for="Noise">Gaussian Noise (in dB)</label>

                <input type="number" id="Noise" name="Noise" value="-15" step="1">

            </td>

        </tr>

        <tr>

            <td>

                <canvas id="constellationCanvas" width="400" height="400"></canvas>

            </td>

        </tr>

    </table>

    <script type="text/javascript" src="mathjs/math.js"></script>

    <script type="text/javascript" src="Constellation.js"></script>

</body>

 

</html>

NOTE : I downloaded the math.js library from Mathjs homepage and placed in local path : mathjs/math.js

NOTE : I took me longer time for me to debug this code than other examples. It seems chatGPT is not well trained with the details of handling the details of canvas. Sometimes there seem to be some bugs in canvas object itself. For example,  if I put the number 2.0 or 1.99 in highlighted part (actually 2.0 is logically correct number), I got unexpected rectangles and blank part in the coordinate plane. I spent long time to figure this out but still don't know why it should be like this.

    for (let i = -2.0; i <= 2.0; i += 0.2) {

        ctx.moveTo(i, -1.98);

        ctx.lineTo(i, 1.98);

        ctx.moveTo(-1.98, i);

        ctx.lineTo(1.98, i);

    }

Another tricky point was about ctx.lineWidth = 1/(canvas.width/4); when I scale up the coordnate using scale() method, I noticed that the linewidth got scaled up accordinly. so I got super thick grid lines. so I needed to scaledown lineWidth before scaling up with scale() method.

Constellation.js

const plotSignal = () => {

    //console.log('plotSignal');

    // Get the canvas element and context

    const canvas = document.getElementById('constellationCanvas');

    const noise = document.getElementById('Noise');

    const ctx = canvas.getContext('2d');

    

    ctx.strokeStyle = 'white';

    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Get the number of samples from the textbox

    const numSamples = document.getElementById('NoOfSample').value;

   

    let noiseLevel_dB = noise.value;

    let noiseLevel = Math.pow(10, noiseLevel_dB/20);

    let signal = [];

    //console.log(noiseLevel_dB);

   

    // Generate an array of random complex numbers

    for (let i = 0; i < numSamples; i++) {

        let real = Math.round(Math.random())*2-1 + gaussianRandom(0, noiseLevel);

        let imag = Math.round(Math.random())*2-1 + gaussianRandom(0, noiseLevel);

        signal.push(math.complex(real, imag));

        //console.log(real);

    }

 

    let real,imag;

    // Scale the canvas

    ctx.save();

    ctx.lineWidth = 1/(canvas.width/4);

    ctx.scale(canvas.width / 4, -canvas.height / 4);

    ctx.translate(2, -2);

 

    // Draw the grid

    ctx.strokeStyle = 'gray';

    ctx.beginPath();

    for (let i = -2.0; i <= 2.0; i += 0.2) {

        ctx.moveTo(i, -1.98);

        ctx.lineTo(i, 1.98);

        ctx.moveTo(-1.98, i);

        ctx.lineTo(1.98, i);

    }

    ctx.stroke();

    // Draw the X and Y axis

    ctx.strokeStyle = 'black';

    ctx.beginPath();

    ctx.moveTo(-2, 0);

    ctx.lineTo(2, 0);

    ctx.moveTo(0, -2);

    ctx.lineTo(0, 2);

    ctx.stroke();

    // Plot the signal

    ctx.fillStyle = 'red';

    for (let i = 0; i < numSamples; i++) {

        real = signal[i].re;

        imag = signal[i].im;

        ctx.fillRect(real-0.025,imag-0.025,0.05,0.05);

    }

 

    ctx.restore();

}

 

function gaussianRandom(mean, stddev) {

    var u1 = Math.random();

    var u2 = Math.random();

    var z0 = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);

    return z0 * stddev + mean;

}