@@ -16,7 +16,7 @@ Preview is best-effort. Some templates may rely on Postman-specific APIs that ar
1616
1717````html
1818// Postman Visualizer: PyPNM-CMTS/ServingGroup/Upstream/OFDMA/PreEqualization/Results/basic
19- // Last Update: 2026-02-26 01 :04:54 MST
19+ // Last Update: 2026-02-28 12 :04:00 MST
2020
2121const response = pm.response.json();
2222
@@ -91,127 +91,6 @@ function normalizeGroupDelay(gd) {
9191 return out;
9292}
9393
94- function normalizeScatterPoints(complexValues, complexDimension) {
95- const arr = Array.isArray(complexValues) ? complexValues : [];
96- if (!arr.length) return [];
97-
98- const dim = n(complexDimension);
99- const out = [];
100-
101- if (Number.isFinite(dim) && dim >= 2) {
102- const step = Math.round(dim);
103- for (let i = 0; i + 1 < arr.length; i += step) {
104- const xi = n(arr[i]);
105- const yi = n(arr[i + 1]);
106- if (xi == null || yi == null) continue;
107- out.push({ x: xi, y: yi });
108- }
109- } else if (Array.isArray(arr[0])) {
110- for (const pair of arr) {
111- if (!Array.isArray(pair) || pair.length < 2) continue;
112- const xi = n(pair[0]);
113- const yi = n(pair[1]);
114- if (xi == null || yi == null) continue;
115- out.push({ x: xi, y: yi });
116- }
117- } else {
118- for (let i = 0; i + 1 < arr.length; i += 2) {
119- const xi = n(arr[i]);
120- const yi = n(arr[i + 1]);
121- if (xi == null || yi == null) continue;
122- out.push({ x: xi, y: yi });
123- }
124- }
125-
126- if (out.length > 8192) {
127- const stride = Math.ceil(out.length / 8192);
128- const sampled = [];
129- for (let i = 0; i < out.length; i += stride) sampled.push(out[i]);
130- return sampled;
131- }
132- return out;
133- }
134-
135- function normalizeComplexCoefficients(complexValues, complexDimension) {
136- const arr = Array.isArray(complexValues) ? complexValues : [];
137- if (!arr.length) return [];
138- const out = [];
139- const dim = n(complexDimension);
140-
141- if (Number.isFinite(dim) && dim >= 2) {
142- const step = Math.round(dim);
143- for (let i = 0; i + 1 < arr.length; i += step) {
144- const re = n(arr[i]);
145- const im = n(arr[i + 1]);
146- if (re == null || im == null) continue;
147- out.push({ re, im });
148- }
149- } else if (Array.isArray(arr[0])) {
150- for (const pair of arr) {
151- if (!Array.isArray(pair) || pair.length < 2) continue;
152- const re = n(pair[0]);
153- const im = n(pair[1]);
154- if (re == null || im == null) continue;
155- out.push({ re, im });
156- }
157- } else {
158- for (let i = 0; i + 1 < arr.length; i += 2) {
159- const re = n(arr[i]);
160- const im = n(arr[i + 1]);
161- if (re == null || im == null) continue;
162- out.push({ re, im });
163- }
164- }
165-
166- return out;
167- }
168-
169- function toDbLinear(mag, floorDb) {
170- const floorLinear = Math.pow(10, floorDb / 20);
171- const clipped = Math.max(mag, floorLinear);
172- return 20 * Math.log10(clipped);
173- }
174-
175- function buildOfdmaAnalyzerSeries(analysis, carrierValues, floorDb = -120, epsilon = 1e-12) {
176- const cv = carrierValues || {};
177- const coeffs = normalizeComplexCoefficients(cv.complex, cv.complex_dimension);
178- if (!coeffs.length) return { preeq_db_points: [], channel_db_points: [] };
179-
180- const freqList = Array.isArray(cv.frequency) ? cv.frequency : [];
181- const spacingHz = n(analysis && analysis.subcarrier_spacing);
182- const firstIdx = n(analysis && analysis.first_active_subcarrier_index);
183- const zeroHz = n(analysis && analysis.subcarrier_zero_frequency);
184- const canBuildAxis = spacingHz != null && firstIdx != null && zeroHz != null;
185- const startHz = canBuildAxis ? (zeroHz + (firstIdx * spacingHz)) : null;
186-
187- const preeqDb = [];
188- const chEstDb = [];
189-
190- for (let i = 0; i < coeffs.length; i += 1) {
191- let fHz = n(freqList[i]);
192- if (fHz == null && startHz != null && spacingHz != null) {
193- fHz = startHz + (i * spacingHz);
194- }
195- if (fHz == null) continue;
196-
197- const re = coeffs[i].re;
198- const im = coeffs[i].im;
199- const magSq = (re * re) + (im * im);
200- const mag = Math.sqrt(magSq);
201- const preDb = toDbLinear(mag, floorDb);
202-
203- let chDb = floorDb;
204- if (magSq >= epsilon) {
205- chDb = -preDb;
206- }
207-
208- preeqDb.push({ x: fHz / 1e6, y: preDb });
209- chEstDb.push({ x: fHz / 1e6, y: chDb });
210- }
211-
212- return { preeq_db_points: preeqDb, channel_db_points: chEstDb };
213- }
214-
21594function buildPayload(r) {
21695 const results = (r && r.results) || {};
21796 const capture = results.capture_details || {};
@@ -275,8 +154,6 @@ function buildPayload(r) {
275154 const endMHz = points[points.length - 1].x;
276155 const stats = computeStats(points.map((p) => p.y));
277156 const gd = normalizeGroupDelay(cv.group_delay);
278- const scatterPoints = normalizeScatterPoints(cv.complex, cv.complex_dimension);
279- const analyzerSeries = buildOfdmaAnalyzerSeries(analysis, cv);
280157 const gdStats = gd.length ? computeStats(gd) : null;
281158 const spacingHz = n(analysis.subcarrier_spacing) || 0;
282159 const windowKey = [Math.round(startMHz*1000)/1000, Math.round(endMHz*1000)/1000, Math.round(spacingHz), points.length].join('|');
@@ -299,15 +176,10 @@ function buildPayload(r) {
299176 mag_max: fmtn(stats.max, 2),
300177 range_label: fmtInt(startMHz) + ' - ' + fmtInt(endMHz) + ' MHz',
301178 window_label: 'Bandwidth (' + fmtInt(startMHz) + ' - ' + fmtInt(endMHz) + ' MHz)',
302- chart_id: 'pre -mag-' + chIndex + '-' + mIndex,
179+ chart_id: 'ce -mag-' + chIndex + '-' + mIndex,
303180 points,
304- gd_chart_id: 'pre -gd-' + chIndex + '-' + mIndex,
181+ gd_chart_id: 'ce -gd-' + chIndex + '-' + mIndex,
305182 gd_points: gd.length ? gd.map((v, i) => ({ x: i, y: v })) : [],
306- scatter_chart_id: 'pre-scatter-' + chIndex + '-' + mIndex,
307- scatter_points: scatterPoints,
308- analyzer_chart_id: 'pre-analyzer-' + chIndex + '-' + mIndex,
309- preeq_db_points: analyzerSeries.preeq_db_points,
310- channel_db_points: analyzerSeries.channel_db_points,
311183 gd_avg: gdStats ? fmtn(gdStats.avg, 4) : 'N/A',
312184 gd_p2p: gdStats && gdStats.min != null && gdStats.max != null ? fmtn(gdStats.max - gdStats.min, 4) : 'N/A',
313185 echo_count: echoes.length,
@@ -453,23 +325,6 @@ const template = `
453325 if(!canvas||!window.Chart||!datasets||!datasets.length) return null;
454326 return new Chart(canvas,{type:'line',data:{datasets},options:{responsive:true,maintainAspectRatio:false,interaction:{mode:'nearest',intersect:false},plugins:{legend:{display:false},title:titleText?{display:true,text:titleText,color:axisText}:{display:false},tooltip:{callbacks:{title:(items)=>items.length?(xTitle==='MHz'?(String(Math.round(items[0].parsed.x))+' MHz'):('Index '+items[0].parsed.x)):'' ,label:(ctx)=>(String(ctx.dataset.label)+': '+ctx.parsed.y.toFixed(2))}}},scales:{x:{type:'linear',title:{display:true,text:xTitle,color:axisText},ticks:{callback:(v)=>xTitle==='MHz'?String(Math.round(v)):String(v),color:axisText},grid:{color:gridColor}},y:{title:{display:true,text:yTitle,color:axisText},ticks:{color:axisText},grid:{color:gridColor}}}}});
455327 }
456- function createScatterChart(canvas, points, titleText){
457- if(!canvas||!window.Chart||!Array.isArray(points)||!points.length) return null;
458- return new Chart(canvas,{
459- type:'scatter',
460- data:{datasets:[{label:'Scatter',data:points,parsing:false,showLine:false,pointRadius:1.2,pointHoverRadius:1.8,backgroundColor:'#3b82f6',borderColor:'#3b82f6'}]},
461- options:{
462- responsive:true,
463- maintainAspectRatio:false,
464- animation:false,
465- plugins:{legend:{display:false},title:titleText?{display:true,text:titleText}:{display:false}},
466- scales:{
467- x:{type:'linear',title:{display:true,text:'I',color:axisText},ticks:{display:false,color:axisText},grid:{display:false,color:gridColor}},
468- y:{type:'linear',title:{display:true,text:'Q',color:axisText},ticks:{display:false,color:axisText},grid:{display:false,color:gridColor}}
469- }
470- }
471- });
472- }
473328 serviceGroups.forEach((sg)=>{
474329 const sgCard=document.createElement('section'); sgCard.className='channel-card';
475330 const sgHead=document.createElement('div'); sgHead.className='channel-head';
@@ -506,14 +361,6 @@ const template = `
506361 } else {
507362 const gdEmpty=document.createElement('div'); gdEmpty.className='chart-box small'; gdEmpty.style.display='grid'; gdEmpty.style.placeItems='center'; gdEmpty.style.color='var(--muted)'; gdEmpty.textContent='No Group Delay'; card.appendChild(gdEmpty);
508363 }
509- if ((row.preeq_db_points && row.preeq_db_points.length) || (row.channel_db_points && row.channel_db_points.length)) {
510- const anLabel=document.createElement('div'); anLabel.className='chart-label'; anLabel.textContent='PreEq Analyzer';
511- card.appendChild(anLabel);
512- const anBox=document.createElement('div'); anBox.className='chart-box small';
513- const anCanvas=document.createElement('canvas'); anCanvas.id=row.analyzer_chart_id;
514- anBox.appendChild(anCanvas);
515- card.appendChild(anBox);
516- }
517364 grid.appendChild(card);
518365 });
519366 wCard.appendChild(grid);
@@ -535,31 +382,6 @@ const template = `
535382 const gd=document.getElementById(row.gd_chart_id);
536383 createLineChart(gd,[{label:'GD',data:row.gd_points,parsing:false,pointRadius:0,borderWidth:1.4,tension:0,borderColor:palette[i%palette.length]}],null,'Index','Group Delay');
537384 }
538- if (row && row.scatter_points && row.scatter_points.length) {
539- const card = cv ? cv.closest('.cm-card') : null;
540- if (card) {
541- const scLabel=document.createElement('div'); scLabel.className='chart-label'; scLabel.textContent='Scatter';
542- card.appendChild(scLabel);
543- const scBox=document.createElement('div'); scBox.className='chart-box small';
544- const scCanvas=document.createElement('canvas'); scCanvas.id=row.scatter_chart_id;
545- scBox.appendChild(scCanvas);
546- card.appendChild(scBox);
547- createScatterChart(scCanvas, row.scatter_points, null);
548- }
549- }
550- if (row && (row.preeq_db_points || row.channel_db_points)) {
551- const anCanvas = document.getElementById(row.analyzer_chart_id);
552- if (anCanvas) {
553- const ds = [];
554- if (Array.isArray(row.preeq_db_points) && row.preeq_db_points.length) {
555- ds.push({ label: 'Applied Pre-EQ (dB)', data: row.preeq_db_points, parsing:false, pointRadius:0, borderWidth:1.5, tension:0, borderColor:'#2563eb' });
556- }
557- if (Array.isArray(row.channel_db_points) && row.channel_db_points.length) {
558- ds.push({ label: 'Estimated Channel (dB)', data: row.channel_db_points, parsing:false, pointRadius:0, borderWidth:1.5, tension:0, borderColor:'#ef4444' });
559- }
560- if (ds.length) createLineChart(anCanvas, ds, null, 'MHz', 'dB');
561- }
562- }
563385 });
564386 });
565387 });
0 commit comments