const mp = 938.27208816; const mn = 939.56542052; class Isotope { constructor(A, Z, BE, symbol){ this.A = A; this.Z = Z; this.N = A - Z; this.BE = BE; this.symbol = symbol; this.mass = Z*mp +this.N*mn - BE*A/1000.; this.stable = false; }; Print(){ console.log(this.A + this.symbol); }; } const size = 30; // size of each ele square const maxN = 177; const maxZ = 118; const padX = 100; const padY = 100; const startY = size*maxZ; const startX = 0; var AllIso = []; // 2D AllIso[N][Z] for( let i = 0; i <= maxN; i++){ const row = []; for( let j = 0; j <= maxZ; j++){ row.push(new Isotope(NaN, NaN, NaN, NaN, NaN)); } AllIso.push(row); } function readLocalFile(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { //console.log(xhr.responseText); let lines = xhr.responseText.split('\n').slice(36); lines.forEach(element => { let z = parseInt(element.substring(11,15)); let a = parseInt(element.substring(16,20)); let sym = element.substring(20,22).trim(); let be = parseFloat(element.substring(56,67).trim()); const iso = new Isotope(a, z, be, sym); if( !isNaN(a) && !isNaN(z)) AllIso[a-z][z] = iso; }); } else { console.error('Error reading the file:', xhr.statusText); } } }; xhr.open('GET', 'Cleopatra/mass20.txt', false); xhr.send(); } function makeElement(x,y, A, text, fillColor){ var square = new paper.Path.Rectangle({ point: [x + size*0.1/2, y + size*0.1/2], size: [size*0.9, size*0.9], fillColor: fillColor, // Filling color of the square //strokeColor: 'black', // Border color of the square //strokeWidth: 1 // Border width of the square }); // Create a text item inside the square var textItemA = new paper.PointText({ point: [x + size / 2 - 2, y + size / 2 + 5], // Center of the square content: A, justification: 'right', fontSize: size * 0.2, // Adjust font size based on the size of the square fillColor: 'black' // Color of the text }); var textItem = new paper.PointText({ point: [x + size / 2 - 2, y + size / 2 + 5], // Center of the square content: text, justification: 'left', fontSize: size * 0.3, // Adjust font size based on the size of the square fillColor: 'black' // Color of the text }); // Group the square and text together var group = new paper.Group([square, textItem, textItemA]); textItemA.position.y -= 5; // Add event handlers for mouseenter and mouseleave events group.onMouseEnter = function (event) { square.fillColor = 'orange'; // Change the filling color when hovering over }; group.onMouseLeave = function (event) { square.fillColor = fillColor; // Restore the original filling color when the mouse leaves }; return group; // Return the group containing the square and text } function checkBounded(num1, num2, num3) { const numbers = [num1, num2, num3]; let countNaN = 0; for (const num of numbers) { if(!isNaN(num) && num < 0) { return false; }else{ countNaN ++; } } if( countNaN == 3) { return true; }else{ return false; } return true; } //#################################### window.onload = function(){ paper.setup('nuclearChart'); const project = paper.project; project.view.viewSize = new paper.Size( maxN * size + padX*2, maxZ*size + padY*2); readLocalFile(); for( let i = 0; i <= maxN; i++){ for( let j = 0; j <= maxZ; j++){ let iso = AllIso[i][j]; if( !isNaN(iso.A) ){ // iso.Print(); let Sp = NaN; let Sn = NaN; let Sa = NaN; if( j > 1) Sp = AllIso[i][j-1].mass + mp - iso.mass; if( i > 1) Sn = AllIso[i-1][j].mass + mn - iso.mass; if( i > 2 && j > 2) Sa = AllIso[i-2][j-2].mass + AllIso[2][2].mass - iso.mass; //if( iso.Z > 55 && iso.N >= 82 ) console.log( iso.A + iso.symbol + " | " + Sp + "," + Sn + "," + Sa); if( checkBounded(Sp, Sn, 1) ){ let Qbm = NaN; let Qbp = NaN; let Qec = NaN; if( i > 0 && j < maxZ ) Qbm = iso.mass - AllIso[i-1][j+1].mass - 0.511; if( j > 0 && i < maxN ) Qbp = iso.mass - AllIso[i+1][j-1].mass - 0.511; if( j > 0 && i < maxN ) Qec = iso.mass - AllIso[i+1][j-1].mass + 0.511; //if( iso.Z > 55 && iso.N >= 82 )console.log( iso.A + iso.symbol + " | " + iso.mass + " | " + Qbm + "," + Qbp + "," + Qec); if( Qbm > 0 || Qbp > 0 || Qec > 0 || (iso.Z > 83 && Sa < 0 ) || (iso.Z < 20 && Sa < 0 ) ){ makeElement(startX + i * size + padX, startY - j*size + padY, AllIso[i][j].A, AllIso[i][j].symbol, 'white'); }else{ makeElement(startX + i * size + padX, startY - j*size + padY, AllIso[i][j].A, AllIso[i][j].symbol, 'grey'); } }else{ makeElement(startX + i * size + padX, startY - j*size + padY, AllIso[i][j].A, AllIso[i][j].symbol, 'white'); } } } } //Draw magic line var magic = [2, 8, 20, 28, 40, 50, 82, 126]; for( let i = 0; i < 8; i++){ let haha1 = new paper.Path(); haha1.strokeColor = 'black'; haha1.strokeWidth = 1; let minY = maxZ; let maxY = 0; for( let Z = 0; Z < maxZ; Z ++){ if( AllIso[magic[i]][Z].A > 0 ){ if( minY > Z) minY = Z; if( maxY < Z) maxY = Z; } } minY -= 1; haha1.moveTo(new paper.Point(startX + padX + magic[i]*size, startY - minY*size + padY)); haha1.lineTo(new paper.Point(startX + padX + magic[i]*size, startY - maxY*size + padY)); let haha2 = new paper.Path(); haha2.strokeColor = 'black'; haha2.strokeWidth = 1; haha2.moveTo(new paper.Point(startX + padX + (magic[i]+1)*size, startY - minY*size + padY)); haha2.lineTo(new paper.Point(startX + padX + (magic[i]+1)*size, startY - maxY*size + padY)); let minX = maxN; let maxX = 0; for( let N = 0; N < maxN; N ++){ if( AllIso[N][magic[i]].A > 0 ){ if( minX > N) minX = N; if( maxX < N) maxX = N; } } maxX += 1; let haha3 = new paper.Path(); haha3.strokeColor = 'black'; haha3.strokeWidth = 1; haha3.moveTo(new paper.Point( startX + minX*size + padX, padY + startY - (magic[i]-1)*size)); haha3.lineTo(new paper.Point( startX + maxX*size + padX, padY + startY - (magic[i]-1)*size)); let haha4 = new paper.Path(); haha4.strokeColor = 'black'; haha4.strokeWidth = 1; haha4.moveTo(new paper.Point( startX + minX*size + padX, padY + startY - (magic[i])*size)); haha4.lineTo(new paper.Point( startX + maxX*size + padX, padY + startY - (magic[i])*size)); } paper.view.draw(); }