Biophysical Model Parameter Estimation Log

Biophysical Model Parameter Estimation Log

ModelFit Recorder

Biophysical Model Parameter Estimation Log
Model Identification & Context
Fitting Criteria
Parameter Fitting Trials

Record each trial's parameter set and objective function result.

Trial ID
Parameter Set Tested (e.g., g_Na=1.2, C_m=1.0)
Objective Function Result
Outcome / Rationale
Remove

Model: ${data.model} | Target System: ${data.system}

`; // 2. Setup Details html += `

I. Model Setup & Criteria

`; html += `
Error Metric${data.errorMetric}
Data Source${data.dataSource}
Parameters Fitted${data.parameters}
`; // 3. Log Table if (logData.length > 0) { html += `

II. Fitting Trial Log (Optimization History)

`; let tableHtml = ``; logData.forEach(item => { const rowColor = item.outcome.toUpperCase().includes('ACCEPTED') ? '#dcfce7' : '#fff'; tableHtml += ``; }); tableHtml += `
Trial ID Parameter Set Tested Error Value Outcome / Rationale
${item.id} ${item.params} ${item.error} ${item.outcome}
`; html += tableHtml; } container.innerHTML = html; } function bmpelSwitchTab(tabId) { document.querySelectorAll('.bmpel-tab-btn').forEach(b => b.classList.remove('active')); document.querySelectorAll('.bmpel-content').forEach(c => c.classList.remove('active')); const idx = tabId === 'setup' ? 0 : (tabId === 'log' ? 1 : 2); document.querySelectorAll('.bmpel-tab-btn')[idx].classList.add('active'); document.getElementById('bmpel-' + tabId).classList.add('active'); if (tabId === 'report') { bmpelRenderReport(); } } function bmpelLoadExample() { if(!confirm("Overwrite current data with example Hodgkin-Huxley fitting data?")) return; document.getElementById('inp-model').value = "Hodgkin-Huxley Neural Model v3"; document.getElementById('inp-system').value = "Squid Giant Axon Firing Rate"; document.getElementById('inp-error-metric').value = "RMS Error (Root Mean Square)"; document.getElementById('inp-data-source').value = "Patch-clamp recording (Exp. ID 45B)"; document.getElementById('inp-parameters').value = "g_Na (Sodium conductance), C_m (Membrane capacitance), V_L (Leak reversal potential)"; // Clear and refill rows document.getElementById('bmpel-log-rows-container').innerHTML = ''; bmpelAddTrialRow("TRIAL 1", "g_Na=1.2; C_m=1.0; V_L=-65", "0.087", "Rejected: Firing rate too high."); bmpelAddTrialRow("TRIAL 2", "g_Na=1.1; C_m=0.8; V_L=-70", "0.015", "ACCEPTED: Best fit to spike shape."); bmpelAddTrialRow("TRIAL 3", "g_Na=1.15; C_m=0.9; V_L=-68", "0.035", "Rejected: Error too high compared to Trial 2."); bmpelRenderReport(); bmpelSwitchTab('report'); } /* --- PDF Generation --- */ async function bmpelGeneratePDF() { bmpelRenderReport(); // Final render check const logData = bmpelGetLogData(); if (logData.length === 0) { alert("Please add trial entries before generating the PDF."); return; } const data = { model: document.getElementById('inp-model').value || "Model Name", system: document.getElementById('inp-system').value || "Target System", errorMetric: document.getElementById('inp-error-metric').value || "Error Metric", dataSource: document.getElementById('inp-data-source').value || "Data Source", parameters: document.getElementById('inp-parameters').value || "Parameters pending." }; const { jsPDF } = window.jspdf; const doc = new jsPDF('l', 'mm', 'a4'); // Landscape for better table fit const teal = [0, 121, 107]; let y = 20; // 1. Header doc.setFillColor(...teal); doc.rect(0, 0, 297, 20, 'F'); doc.setTextColor(255, 255, 255); doc.setFontSize(16); doc.text(`Biophysical Model Parameter Estimation Log`, 14, 13); // 2. Setup Details y = 30; doc.setTextColor(0, 0, 0); doc.setFontSize(10); const setupTable = [ ['Model/System', `${data.model} / ${data.system}`], ['Parameters Fitted', data.parameters], ['Error Metric', data.errorMetric], ['Data Source', data.dataSource] ]; doc.autoTable({ startY: y, head: [['MODEL SETUP & CONTEXT', '']], body: setupTable, theme: 'grid', headStyles: { fillColor: teal, fontSize: 10 }, styles: { fontSize: 9 }, columnStyles: { 0: { fontStyle: 'bold', fillColor: [240, 240, 240] } } }); y = doc.lastAutoTable.finalY + 10; // 3. Log Table doc.setFontSize(12); doc.setFont("helvetica", "bold"); doc.setTextColor(...teal); doc.text("Fitting Trial History", 14, y); y += 5; const tableBody = logData.map(item => [ item.id, item.params, item.error, item.outcome ]); doc.autoTable({ startY: y, head: [['Trial ID', 'Parameter Set Tested', 'Error Value', 'Outcome / Rationale']], body: tableBody, theme: 'grid', headStyles: { fillColor: teal, fontSize: 10 }, styles: { fontSize: 8.5 }, columnStyles: { 0: { cellWidth: 20, fontStyle: 'bold' }, 1: { cellWidth: 65, font: 'courier' }, 2: { cellWidth: 20, halign: 'center' }, 3: { cellWidth: 'auto', overflow: 'linebreak' } }, didParseCell: function(data) { if (data.section === 'body' && data.column.index === 3) { if (data.cell.raw.toUpperCase().includes('ACCEPTED')) { data.cell.styles.fillColor = [200, 240, 200]; } } } }); // 4. Final Note let finalY = doc.lastAutoTable.finalY + 15; if (finalY > 180) { doc.addPage(); finalY = 30; } doc.setFontSize(10); doc.text(`Final Accepted Parameter Set (Trial ${logData.filter(p => p.outcome.toUpperCase().includes('ACCEPTED')).pop()?.id || 'N/A'}) must be transferred to the model file.`, 14, finalY); doc.save(`ParameterEstimation_Log.pdf`); }
Scroll to Top