Plot Constellation with Phase Delay


this code is created first by chatGPT on Jan 28 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 :


The code in this note is made by manual modification to the script in this note.


Usage : Click on [Constellation] button. Whenever you click on it, you will get different constellation. If you roll over each of the text box, you will get spin buttons on the right end of the textbox. Click on up/down arrow on the spin button to change the values.

NOTE : The plot shown above is the result of the expression : e^(θ i) sig, where sig is the complex arragy.


NOTE : The part highlighted in red is the one that I added. The main purpose of this script is to show how to do complex number operation in math.js library.


<!DOCTYPE html>




    <title>Constellation Plot</title>





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



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

                <input type="number" id="NoOfSample" name="NoOfSample" value="600" min="1" step="100" onClick="plotSignal()">

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





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

                <input type="number" id="Noise" name="Noise" value="-15" step="1" onClick="plotSignal()">





                <label for="Noise">e^(θ i) </label>

                <input type="number" id="theta" name="Noise" value="30" step="1" onClick="plotSignal()">





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




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

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






const plotSignal = () => {

    // Get the canvas element and context

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

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

    const th = document.getElementById('theta').value * Math.PI/180.0;

    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;


    // Generate an array of random complex numbers


    let noiseLevel_dB = noise.value;

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

    let signal = [];


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




    let real,imag;

    // Scale the canvas;

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

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

    ctx.translate(2, -2);


    // Draw the grid

    ctx.strokeStyle = 'gray';


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




    // Draw the X and Y axis

    ctx.strokeStyle = 'black';


    ctx.moveTo(-2, 0);

    ctx.lineTo(2, 0);

    ctx.moveTo(0, -2);

    ctx.lineTo(0, 2);



    // Plot the signal

    ctx.fillStyle = 'red';

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

        let s = math.multiply( math.pow(Math.E, math.complex(0, th)), signal[i] );

        real =;

        imag =;







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;