Flow Cytometry Gating Strategy Documenter

Flow Cytometry Gating Strategy Documenter

1. Project & Sample Metadata

2. Add Gating Step

3. Current Gating Strategy Steps

Gating Strategy Document - T-cell Activation Study

A. Project Metadata

B. Detailed Gating Strategy

Step Population ID Parent Pop. Markers Used Type Gating Logic / Definition

No gating steps defined.

'; } appState.gatingSteps.forEach(function(step) { var item = document.createElement('div'); item.className = 'gsd-step-list-item'; item.innerHTML = ` Step ${step.id}: ${step.popId} from ${step.parent} `; stepsListDiv.appendChild(item); }); // Add remove listeners stepsListDiv.querySelectorAll('.gsd-remove-btn').forEach(function(btn) { btn.addEventListener('click', function() { var id = parseInt(btn.dataset.id); appState.gatingSteps = appState.gatingSteps.filter(function(s) { return s.id !== id; }); saveState(); renderConfigTab(); }); }); } addStepBtn.addEventListener('click', function() { var popId = popIdInput.value.trim(); var parentPop = parentPopInput.value.trim(); var markers = markersInput.value.trim(); var gateType = gateTypeSelect.value; var logicDesc = logicDescInput.value.trim(); if (!popId || !parentPop || !markers || !logicDesc) { alert("Please fill in Population ID, Parent, Markers, and Logic Description."); return; } var newStep = { id: Date.now(), popId: popId, parent: parentPop, markers: markers, type: gateType, logic: logicDesc }; appState.gatingSteps.push(newStep); appState.gatingSteps.sort(function(a, b) { return a.id - b.id; }); // Sort by creation time saveState(); renderConfigTab(); // Clear inputs popIdInput.value = ''; parentPopInput.value = ''; markersInput.value = ''; logicDescInput.value = ''; gateTypeSelect.value = 'Scatter'; }); // Update button action updateBtn.addEventListener("click", function() { // Update metadata from form appState.metadata.project = projectNameInput.value; appState.metadata.experimenter = experimenterInput.value; appState.metadata.instrument = instrumentInput.value; appState.metadata.sampleType = sampleTypeInput.value; saveState(); renderDashboardTab(); showTab(1); // Switch to Dashboard }); // --- Core Logic: Dashboard Rendering --- function renderDashboardTab() { // Render titles projectTitleDisplay.textContent = `Gating Strategy Document - ${appState.metadata.project}`; // Render metadata table metadataBody.innerHTML = ` Project Name${appState.metadata.project} Experimenter/Analyst${appState.metadata.experimenter} Instrument Model${appState.metadata.instrument} Sample Type${appState.metadata.sampleType} `; // Render strategy table strategyTableBody.innerHTML = ''; if (appState.gatingSteps.length === 0) { strategyTableBody.innerHTML = 'No gating steps defined.'; return; } appState.gatingSteps.forEach(function(step, index) { var stepNum = index + 1; strategyTableBody.innerHTML += ` ${stepNum} ${step.popId} ${step.parent} ${step.markers} ${step.type} ${step.logic} `; }); } // --- PDF Download --- pdfBtn.addEventListener("click", function() { var jsPDF = window.jspdf.jsPDF; var projectSlug = appState.metadata.project.replace(/[^a-zA-Z0-9\s]/g, '').replace(/\s/g, '_').substring(0, 30) || 'Gating_Strategy'; var fileName = `${projectSlug}_Strategy_Document.pdf`; // Temporarily adjust minimum width for better PDF quality capture var tableContainer = document.getElementById('gsd-strategy-table-container'); var originalMinWidth = tableContainer.style.minWidth; tableContainer.style.minWidth = '1000px'; html2canvas(exportArea, { scale: 2, useCORS: true, backgroundColor: '#ffffff' }).then(function(canvas) { // Restore original minWidth tableContainer.style.minWidth = originalMinWidth; var imgData = canvas.toDataURL('image/png'); var doc = new jsPDF({ orientation: 'l', // Landscape is better for wide tables unit: 'pt', format: 'a4' }); var pdfWidth = doc.internal.pageSize.getWidth(); var pdfHeight = doc.internal.pageSize.getHeight(); var imgProps = doc.getImageProperties(imgData); var imgWidth = imgProps.width; var imgHeight = imgProps.height; var margin = 40; var usableWidth = pdfWidth - (2 * margin); var ratio = usableWidth / imgWidth; var scaledHeight = imgHeight * ratio; var usablePageHeight = pdfHeight - (2 * margin); var heightLeft = scaledHeight; var position = 0; while (heightLeft > 0) { // Add content with appropriate vertical offset for pagination doc.addImage(imgData, 'PNG', margin, position + margin, usableWidth, scaledHeight); heightLeft -= usablePageHeight; position -= usablePageHeight; if (heightLeft > 0) { doc.addPage(); } } doc.save(fileName); }).catch(function(err) { tableContainer.style.minWidth = originalMinWidth; // Restore on error console.error("GSD PDF Error:", err); // alert("An error occurred while generating the PDF."); // Per spec }); }); // --- Initial Load --- loadState(); renderConfigTab(); renderDashboardTab(); showTab(0); });
Scroll to Top