UNPKG

hyphy-scope

Version:

Reusable Svelte components for HyPhy analysis visualization

104 lines (103 loc) 3.15 kB
/** * FUBAR (Fast Unconstrained Bayesian AppRoximation) utility functions */ /** * Get summary statistics for FUBAR results */ export function getFubarSummary(data, posteriorProbability = 0.9) { if (!data?.MLE?.content) { return { positiveSites: 0, negativeSites: 0, totalSites: 0 }; } const flattenedData = Object.values(data.MLE.content).flat(); const positiveSites = flattenedData.filter(row => row[4] > posteriorProbability).length; const negativeSites = flattenedData.filter(row => row[3] > posteriorProbability).length; return { positiveSites, negativeSites, totalSites: flattenedData.length }; } /** * Get site-by-site data for FUBAR results */ export function getFubarSiteData(data) { if (!data?.MLE?.content) return []; const flattenedData = Object.values(data.MLE.content).flat(); const partitionColumn = getPartitionColumn(data); return flattenedData.map((row, index) => ({ Site: index + 1, Partition: partitionColumn[index] + 1, α: row[0], β: row[1], 'α-β': row[2], 'Prob[α>β]': row[3], 'Prob[α<β]': row[4] })); } /** * Get partition column mapping */ export function getPartitionColumn(data) { if (!data?.['data partitions']) return []; const flattenedLength = Object.values(data.MLE.content).flat().length; const partitionColumn = new Array(flattenedLength).fill(0); Object.entries(data['data partitions']).forEach(([key, val], partitionIndex) => { val.coverage[0].forEach(siteIndex => { partitionColumn[siteIndex] = partitionIndex; }); }); return partitionColumn; } /** * Extract tree newick string from various input formats */ export function getTreeNewick(data) { if (!data?.input?.trees) return null; const trees = data.input.trees; // Handle different tree formats if (typeof trees === 'string') { return trees; } else if (Array.isArray(trees)) { return trees[0] || null; } else if (typeof trees === 'object') { const treeKeys = Object.keys(trees); return treeKeys.length > 0 ? trees[treeKeys[0]] : null; } return null; } /** * Get grid data for a specific site */ export function getGridDataForSite(data, site) { if (!data?.posterior || !data?.['data partitions'] || !data.grid) { return data.grid; } // Find partition and index for this site let partition = 0; let index = -1; const partitions = Object.values(data['data partitions']); for (let p = 0; p < partitions.length; p++) { const coverage = partitions[p].coverage[0]; const idx = coverage.indexOf(site - 1); if (idx > -1) { partition = p; index = idx; break; } } if (index === -1) return data.grid; // Get site-specific posterior const sitePosterior = data.posterior[partition][index][0]; // Combine with grid coordinates return data.grid.map((d, i) => [d[0], d[1], sitePosterior[i]]); }