Align INI params with OSKAR docs, add Gaussian source support, clean up WGS84 export layout#49
Conversation
…, add Bz to UV, replace hardcoded path, add sky model validation, add WGS84 format option, update Leaflet Co-authored-by: Geovannisz <82838501+Geovannisz@users.noreply.github.com>
…dback Co-authored-by: Geovannisz <82838501+Geovannisz@users.noreply.github.com>
…alidation Co-authored-by: Geovannisz <82838501+Geovannisz@users.noreply.github.com>
…ence; swap position.txt to lon,lat,alt Co-authored-by: Geovannisz <82838501+Geovannisz@users.noreply.github.com>
…MM:SS regex to accept single-digit min/sec Co-authored-by: Geovannisz <82838501+Geovannisz@users.noreply.github.com>
…del table Co-authored-by: Geovannisz <82838501+Geovannisz@users.noreply.github.com>
Co-authored-by: Geovannisz <82838501+Geovannisz@users.noreply.github.com>
… to all sky model generators Co-authored-by: Geovannisz <82838501+Geovannisz@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Alinha o gerador de layouts e arquivos de configuração com convenções/documentação do OSKAR, adicionando suporte a fontes Gaussianas no sky model, melhorando a cobertura UV (incluindo componente Bz) e reorganizando a exportação de coordenadas (WGS84/ECEF/ENU) na UI.
Changes:
- Ajusta geração/exportação de coordenadas WGS84 para
lon,lat,alte simplifica o painel de exportação (WGS84 dentro do seletor de formatos). - Expande o sky model para o formato OSKAR de 12 colunas (incluindo RM e parâmetros Gaussianos), com ordenação na tabela.
- Atualiza simulador de cobertura UV (CPU + WebGPU) para considerar
Bze baseline 3D; audita/expande parâmetros dos geradores de INI e tooltips.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| python/telescope_gen.py | Torna paths configuráveis via CLI e ajusta ordem de colunas WGS84. |
| js/uv_coverage.js | Inclui Bz no cálculo de UV e baseline (CPU + WGSL/WebGPU). |
| js/sky_model.js | Suporte a RM e parâmetros Gaussianos; validação parcial; ordenação na tabela. |
| js/map.js | Atualiza URLs de assets do Leaflet para 1.9.4. |
| js/ini_generator.js | Grande auditoria de params/tooltips; mudanças de defaults e tipos; novos params. |
| js/export.js | Remove campo WGS84 standalone; usa painel WGS84 alternativo e ajusta ZIP export. |
| index.html | Atualiza Leaflet para 1.9.4; ajusta UI de export e sky model table header. |
| css/styles.css | Estilos para cabeçalhos ordenáveis da tabela do sky model. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /** | ||
| * Analisa o texto do modo avançado e importa as fontes. | ||
| */ | ||
| _parseAdvancedInput() { | ||
| const textarea = document.getElementById('sky-advanced-text'); | ||
| if (!textarea) return; | ||
|
|
||
| const lines = textarea.value.trim().split('\n'); | ||
| let imported = 0; | ||
|
|
||
| for (const line of lines) { | ||
| const trimmed = line.trim(); | ||
| if (!trimmed || trimmed.startsWith('#')) continue; | ||
|
|
||
| const parts = trimmed.split(/\s+/); | ||
| if (parts.length < 3) continue; | ||
|
|
||
| this.sources.push({ | ||
| ra: parseFloat(parts[0]) || 0, | ||
| dec: parseFloat(parts[1]) || 0, | ||
| flux: parseFloat(parts[2]) || 0, | ||
| q: parseFloat(parts[3]) || 0, | ||
| u: parseFloat(parts[4]) || 0, | ||
| v: parseFloat(parts[5]) || 0, | ||
| refFreq: parseFloat(parts[6]) || SKY_DEFAULT_REF_FREQ, | ||
| spectralIndex: parseFloat(parts[7]) || 0, | ||
| major: parseFloat(parts[8]) || 0, | ||
| minor: parseFloat(parts[9]) || 0, | ||
| pa: parseFloat(parts[10]) || 0 | ||
| rotationMeasure: parseFloat(parts[8]) || 0, | ||
| major: parseFloat(parts[9]) || 0, | ||
| minor: parseFloat(parts[10]) || 0, | ||
| pa: parseFloat(parts[11]) || 0 | ||
| }); | ||
| imported++; | ||
| } |
There was a problem hiding this comment.
No modo avançado, _parseAdvancedInput() adiciona fontes diretamente em this.sources sem aplicar _validateSource(). Isso permite importar RA/Dec fora do intervalo e fluxos negativos, apesar da validação existir e ser aplicada no fluxo de "Fonte Pontual Individual". Sugestão: validar cada linha (e.g., rejeitar/avisar e não importar) para manter o comportamento consistente entre modos.
| @@ -430,9 +536,10 @@ | |||
| dec: dec, | |||
| flux: flux, | |||
| q: 0, u: 0, v: 0, | |||
| refFreq: SKY_DEFAULT_REF_FREQ, | |||
| spectralIndex: 0, | |||
| major: 0, minor: 0, pa: 0 | |||
| refFreq: refFreq, | |||
| spectralIndex: spix, | |||
| rotationMeasure: 0, | |||
| major: major, minor: minor, pa: pa | |||
| }); | |||
There was a problem hiding this comment.
generateGrid() cria RA/Dec por soma direta (centerRA + ..., centerDec + ...) e insere as fontes sem validação/wrap/clamp. Dependendo de n e spacing, isso pode gerar RA >= 360 ou Dec fora de [-90, 90], contrariando as regras introduzidas em _validateSource(). Considere aplicar wrap de RA para [0,360) e clamp de Dec (ou validar e rejeitar) também para o modo grid.
| key: 'image_type', | ||
| section: 'image', | ||
| label: 'Tipo de imagem', | ||
| tooltip: 'Tipo de imagem a gerar. I, Q, U, V são parâmetros de Stokes. PSF gera a função de espalhamento pontual.', | ||
| tooltip: 'Tipo de imagem a gerar. "Linear (I,Q,U,V)" gera mapas de parâmetros de Stokes. "Stokes I" gera apenas a intensidade total. "PSF" gera o Point Spread Function (feixe sintetizado) sem sinal astronômico.', | ||
| type: 'select', | ||
| defaultValue: 'I', | ||
| category: 'essential', | ||
| required: true, | ||
| defaultValue: 'Linear (I,Q,U,V)', | ||
| category: 'recommended', | ||
| options: [ | ||
| { value: 'Linear (I,Q,U,V)', label: 'Linear (I,Q,U,V)' }, | ||
| { value: 'XX', label: 'XX' }, | ||
| { value: 'XY', label: 'XY' }, | ||
| { value: 'YX', label: 'YX' }, | ||
| { value: 'YY', label: 'YY' }, | ||
| { value: 'I', label: 'Stokes I' }, | ||
| { value: 'Q', label: 'Stokes Q' }, | ||
| { value: 'U', label: 'Stokes U' }, | ||
| { value: 'V', label: 'Stokes V' }, | ||
| { value: 'PSF', label: 'PSF' }, | ||
| { value: 'LINEAR', label: 'Linear (XX, XY, YX, YY)' } | ||
| { value: 'PSF', label: 'PSF' } | ||
| ] |
There was a problem hiding this comment.
Em OSKAR_IMAGER_PARAMS.image_type, os valores das opções foram alterados para strings descritivas (ex.: "Linear (I,Q,U,V)") e serão escritos literalmente no arquivo .ini. O oskar_imager normalmente espera tokens específicos (ex.: "LINEAR", "I", "Q", "U", "V", "PSF"); com o valor atual o .ini tende a ficar inválido para o OSKAR. Ajuste para manter os value como os tokens aceitos pelo OSKAR e use as descrições apenas no label.
| if (!/^\d+(\.\d+)?$/.test(value) && !/^\d+:\d{1,2}:\d{1,2}(\.\d+)?$/.test(value)) { | ||
| return 'A duração deve ser em segundos (ex: 3600) ou formato HH:MM:SS.S.'; | ||
| } | ||
| if (/^\d+(\.\d+)?$/.test(value) && Number(value) <= 0) { |
There was a problem hiding this comment.
A validação do campo length aceita o formato HH:MM:SS.S, mas não garante que a duração seja positiva nesse formato (por exemplo, "0:00:00" passa). Como o comentário indica que a duração deve ser positiva, considere converter HH:MM:SS.S para segundos e rejeitar valores <= 0 também nesse caso.
| if (!/^\d+(\.\d+)?$/.test(value) && !/^\d+:\d{1,2}:\d{1,2}(\.\d+)?$/.test(value)) { | |
| return 'A duração deve ser em segundos (ex: 3600) ou formato HH:MM:SS.S.'; | |
| } | |
| if (/^\d+(\.\d+)?$/.test(value) && Number(value) <= 0) { | |
| const numericSecondsPattern = /^\d+(\.\d+)?$/; | |
| const hmsPattern = /^\d+:\d{1,2}:\d{1,2}(\.\d+)?$/; | |
| if (!numericSecondsPattern.test(value) && !hmsPattern.test(value)) { | |
| return 'A duração deve ser em segundos (ex: 3600) ou formato HH:MM:SS.S.'; | |
| } | |
| let totalSeconds; | |
| if (numericSecondsPattern.test(value)) { | |
| totalSeconds = Number(value); | |
| } else { | |
| const parts = value.split(':'); | |
| const hours = Number(parts[0]); | |
| const minutes = Number(parts[1]); | |
| const seconds = Number(parts[2]); | |
| totalSeconds = (hours * 3600) + (minutes * 60) + seconds; | |
| } | |
| if (Number.isNaN(totalSeconds) || totalSeconds <= 0) { |
| // Indicador de direção por coluna | ||
| const sortCols = [ | ||
| { key: 'ra', label: 'RA (°)' }, | ||
| { key: 'dec', label: 'Dec (°)' }, | ||
| { key: 'flux', label: 'I (Jy)' }, | ||
| { key: 'spectralIndex', label: 'Índ. Esp.' }, | ||
| { key: 'major', label: 'Tipo' } | ||
| ]; | ||
|
|
||
| let html = '<tr><th>#</th>'; | ||
| for (const col of sortCols) { | ||
| let arrow = ''; | ||
| if (this._sortColumn === col.key) { | ||
| arrow = this._sortAsc ? ' ▲' : ' ▼'; | ||
| } | ||
| html += `<th class="sky-sortable-th" data-sort-key="${col.key}">${col.label}${arrow}</th>`; | ||
| } | ||
| html += '<th>Ação</th></tr>'; | ||
|
|
||
| for (const origIdx of sortedIndices) { | ||
| const src = this.sources[origIdx]; | ||
| const isExtended = (src.major > 0 || src.minor > 0); | ||
| const typeLabel = isExtended | ||
| ? `<span title="Gaussiana: ${src.major.toFixed(1)}″×${src.minor.toFixed(1)}″ PA=${src.pa.toFixed(0)}°" style="color:var(--primary-color);font-weight:600;">Gauss</span>` | ||
| : '<span style="opacity:0.6;">Pont.</span>'; | ||
| html += ` | ||
| <tr> | ||
| <td>${idx + 1}</td> | ||
| <td>${origIdx + 1}</td> | ||
| <td>${src.ra.toFixed(4)}</td> | ||
| <td>${src.dec.toFixed(4)}</td> | ||
| <td>${src.flux.toFixed(4)}</td> | ||
| <td>${src.spectralIndex.toFixed(2)}</td> | ||
| <td><button class="sky-remove-btn" data-index="${idx}" title="Remover fonte">✕</button></td> | ||
| <td>${typeLabel}</td> | ||
| <td><button class="sky-remove-btn" data-index="${origIdx}" title="Remover fonte">✕</button></td> | ||
| </tr> | ||
| `; | ||
| }); | ||
| } | ||
|
|
There was a problem hiding this comment.
A tabela de fontes agora é re-renderizada sem a coluna de frequência de referência (refFreq), mas o HTML da página mantém a coluna "Freq₀ (Hz)". Isso causa inconsistência na UI e dificulta inspecionar o catálogo gerado/importado. Inclua refFreq na renderização da tabela (e na lista de ordenação, se aplicável) ou remova/atualize a coluna correspondente no HTML para manter os cabeçalhos alinhados.
Multi-part alignment of the application with the OSKAR TutorialOSKAR.tex reference, plus UI/UX improvements requested by the project maintainer.
Changes across sessions
Critical bug:
layout_wgs84.txtandposition.txtcoordinate orderlon,lat,altto match OSKAR's expected format (JS frontend + Python backend)INI generator audit (
js/ini_generator.js)OSKAR_INI_PARAMS,OSKAR_IMAGER_PARAMS,OSKAR_BEAM_PATTERN_PARAMS) aligned with TutorialOSKAR.texhealpix_fits/min_peak_fraction,spectral_index/seed, 7 generator params (generator/grid/*,generator/random_power_law/power,generator/healpix/*),noise/freq1000000000) across all generatorslengthfield changed totexttype to accept both seconds andHH:MM:SSformatoskar_sim_interferometerconsistencyUV coverage: include Bz component
Bzto both CPU and WebGPU compute paths:v = -Bx·sin(δ)·cos(H) + By·sin(δ)·sin(H) + Bz·cos(δ)√(Bx² + By² + Bz²).zdefault to0(preserves coplanar behavior)Sky model: Gaussian/extended source support
All four generation modes (single, grid, random, power-law) now expose the full 12-column OSKAR sky model format:
_buildGaussianFields(prefix)helper avoids duplication across modesSky model validation
_validateSource()enforces RA ∈ [0°, 360°), Dec ∈ [-90°, +90°], Flux ≥ 0Export section cleanup
export-layout-wgs84-altInfrastructure
python/telescope_gen.pywithos.path.dirname-relative paths +argparseCLImin/maxattributes added to sky model HTML inputs💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.