RECIST Calculator: Measure Tumor Response
:root {
–primary-color: #004a99;
–success-color: #28a745;
–background-color: #f8f9fa;
–text-color: #333;
–border-color: #ddd;
–card-background: #fff;
–shadow: 0 2px 5px rgba(0,0,0,0.1);
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(–background-color);
color: var(–text-color);
line-height: 1.6;
margin: 0;
padding: 0;
}
.container {
max-width: 1000px;
margin: 20px auto;
padding: 20px;
background-color: var(–card-background);
border-radius: 8px;
box-shadow: var(–shadow);
}
header {
background-color: var(–primary-color);
color: white;
padding: 20px 0;
text-align: center;
margin-bottom: 20px;
border-radius: 8px 8px 0 0;
}
header h1 {
margin: 0;
font-size: 2.2em;
}
.calculator-section {
margin-bottom: 30px;
padding: 20px;
border: 1px solid var(–border-color);
border-radius: 6px;
background-color: var(–card-background);
}
.calculator-section h2 {
color: var(–primary-color);
margin-top: 0;
border-bottom: 2px solid var(–primary-color);
padding-bottom: 10px;
margin-bottom: 20px;
}
.input-group {
margin-bottom: 15px;
display: flex;
flex-direction: column;
gap: 5px;
}
.input-group label {
font-weight: bold;
display: block;
margin-bottom: 5px;
}
.input-group input[type="number"],
.input-group select {
width: 100%;
padding: 10px;
border: 1px solid var(–border-color);
border-radius: 4px;
box-sizing: border-box;
font-size: 1em;
}
.input-group input[type="number"]:focus,
.input-group select:focus {
border-color: var(–primary-color);
outline: none;
box-shadow: 0 0 0 2px rgba(0, 74, 153, 0.2);
}
.helper-text {
font-size: 0.85em;
color: #666;
margin-top: 5px;
}
.error-message {
color: #dc3545;
font-size: 0.85em;
margin-top: 5px;
display: none; /* Hidden by default */
}
.error-message.visible {
display: block;
}
.button-group {
display: flex;
gap: 10px;
margin-top: 20px;
flex-wrap: wrap;
}
.button-group button {
padding: 10px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1em;
transition: background-color 0.3s ease;
flex-grow: 1;
min-width: 120px;
}
.btn-calculate {
background-color: var(–primary-color);
color: white;
}
.btn-calculate:hover {
background-color: #003366;
}
.btn-reset {
background-color: #6c757d;
color: white;
}
.btn-reset:hover {
background-color: #5a6268;
}
.btn-copy {
background-color: #ffc107;
color: #212529;
}
.btn-copy:hover {
background-color: #e0a800;
}
#results-container {
margin-top: 30px;
padding: 20px;
border: 1px solid var(–border-color);
border-radius: 6px;
background-color: var(–card-background);
}
#results-container h3 {
color: var(–primary-color);
margin-top: 0;
border-bottom: 2px solid var(–primary-color);
padding-bottom: 10px;
margin-bottom: 20px;
}
.result-item {
margin-bottom: 15px;
font-size: 1.1em;
}
.result-item strong {
color: var(–primary-color);
min-width: 200px;
display: inline-block;
}
.primary-result {
background-color: var(–success-color);
color: white;
padding: 15px;
border-radius: 5px;
text-align: center;
font-size: 1.5em;
font-weight: bold;
margin-bottom: 20px;
box-shadow: inset 0 0 10px rgba(0,0,0,0.2);
}
.primary-result span {
font-size: 0.8em;
display: block;
margin-top: 5px;
font-weight: normal;
}
.formula-explanation {
font-size: 0.9em;
color: #555;
margin-top: 15px;
padding-top: 10px;
border-top: 1px dashed #ccc;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
overflow-x: auto; /* Make table scrollable */
display: block; /* Needed for overflow-x */
white-space: nowrap; /* Prevent wrapping within cells */
}
th, td {
padding: 10px 15px;
border: 1px solid var(–border-color);
text-align: left;
}
thead {
background-color: var(–primary-color);
color: white;
}
tbody tr:nth-child(even) {
background-color: #f2f2f2;
}
caption {
font-size: 1.1em;
font-weight: bold;
color: var(–primary-color);
margin-bottom: 10px;
text-align: left;
}
canvas {
max-width: 100%;
height: auto;
display: block;
margin: 20px auto;
border: 1px solid var(–border-color);
border-radius: 4px;
}
.chart-container {
position: relative;
width: 100%;
margin-top: 20px;
padding: 15px;
background-color: var(–card-background);
border: 1px solid var(–border-color);
border-radius: 6px;
}
.chart-container h3 {
color: var(–primary-color);
margin-top: 0;
border-bottom: 2px solid var(–primary-color);
padding-bottom: 10px;
margin-bottom: 20px;
}
.article-content {
margin-top: 40px;
padding: 20px;
background-color: var(–card-background);
border: 1px solid var(–border-color);
border-radius: 6px;
}
.article-content h2, .article-content h3 {
color: var(–primary-color);
margin-top: 25px;
margin-bottom: 15px;
border-bottom: 1px solid #eee;
padding-bottom: 5px;
}
.article-content h2 {
font-size: 1.8em;
border-bottom-color: var(–primary-color);
}
.article-content h3 {
font-size: 1.4em;
}
.article-content p, .article-content ul, .article-content ol {
margin-bottom: 15px;
}
.article-content ul, .article-content ol {
padding-left: 25px;
}
.article-content li {
margin-bottom: 8px;
}
.faq-item {
margin-bottom: 15px;
}
.faq-item strong {
display: block;
color: var(–primary-color);
margin-bottom: 5px;
}
.internal-links {
margin-top: 30px;
padding: 20px;
background-color: var(–card-background);
border: 1px solid var(–border-color);
border-radius: 6px;
}
.internal-links h3 {
color: var(–primary-color);
margin-top: 0;
border-bottom: 2px solid var(–primary-color);
padding-bottom: 10px;
margin-bottom: 20px;
}
.internal-links ul {
list-style: none;
padding: 0;
}
.internal-links li {
margin-bottom: 10px;
}
.internal-links a {
color: var(–primary-color);
text-decoration: none;
font-weight: bold;
}
.internal-links a:hover {
text-decoration: underline;
}
.internal-links p {
font-size: 0.9em;
color: #555;
margin-top: 5px;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.container {
margin: 10px;
padding: 15px;
}
header h1 {
font-size: 1.8em;
}
.button-group {
flex-direction: column;
gap: 10px;
}
.button-group button {
width: 100%;
min-width: unset;
}
table {
font-size: 0.9em;
}
th, td {
padding: 8px 10px;
}
canvas {
width: 100%;
}
}
RECIST 1.1 Measurement Inputs
RECIST 1.1 Assessment Results
— Awaiting Input —
RECIST Response Category
Target Lesion Sum of Diameters (SLD):
— mm
Baseline Target Lesion Sum of Diameters (SLD):
— mm
Percentage Change in SLD:
— %
Non-Target Lesion Assessment:
—
New Lesion Assessment:
—
RECIST 1.1 Response Categories
RECIST Response Visualization
Visual representation of response categories based on SLD change.
RECIST 1.1 Response Criteria Summary
| Category |
Criteria |
| Complete Response (CR) |
Disappearance of all target lesions. Any pathological lymph nodes must have reduction in short axis to < 10 mm. Disappearance of all non-target lesions. No new lesions. |
| Partial Response (PR) |
At least a 30% decrease in the sum of diameters (SLD) of target lesions, taking baseline SLD as reference. |
| Progressive Disease (PD) |
At least a 20% increase in the SLD of target lesions, taking the smallest SLD recorded since treatment started or the baseline SLD if that is the smallest. In addition to the relative increase of 20%, the SLD must also demonstrate an absolute increase of at least 5 mm. Appearance of one or more new lesions. Qualitative or quantitative progression of existing non-target lesions. |
| Stable Disease (SD) |
Neither sufficient shrinkage to qualify for PR nor sufficient increase to qualify for PD, taking the smallest SLD recorded since the treatment started as reference. |
What is RECIST?
RECIST stands for Response Evaluation Criteria in Solid Tumors. It is a standardized set of guidelines used in clinical trials to assess how solid tumors respond to cancer treatments. The primary goal of RECIST is to provide a consistent and reproducible method for evaluating tumor shrinkage or growth, allowing researchers and clinicians to objectively compare the efficacy of different therapies across various studies and institutions. The most commonly used version is RECIST 1.1.
Who should use it?
RECIST is primarily used by oncologists, radiologists, clinical researchers, and pharmaceutical companies involved in cancer drug development and clinical trials. It helps in:
- Objectively measuring tumor response to therapy.
- Standardizing response assessment across different studies.
- Making informed decisions about treatment continuation or modification.
- Reporting trial results consistently.
Common Misconceptions:
- RECIST measures all tumor burden: RECIST focuses on specific "target" lesions and the overall status of "non-target" lesions, not every single tumor deposit.
- RECIST is the only measure of success: While crucial, RECIST is often considered alongside other endpoints like overall survival, progression-free survival, and quality of life.
- RECIST is static: The criteria have evolved (e.g., from RECIST 1.0 to 1.1) and may continue to be refined.
RECIST 1.1 Formula and Mathematical Explanation
The RECIST 1.1 criteria involve a systematic approach to measuring tumor burden. The core calculation revolves around the sum of the diameters of selected "target" lesions and the assessment of "non-target" lesions and new lesions.
Target Lesion Measurement
For target lesions, the longest diameter (LD) and shortest diameter (SD) are measured. The product of these two diameters (LD x SD) is often used, but for RECIST 1.1, the primary metric is the Sum of Longest Diameters (SLD). If multiple target lesions are selected (up to 5 total, with a maximum of 2 per organ), their longest diameters are summed.
The key calculation is the percentage change in the SLD from baseline:
Percentage Change in SLD = ((Current SLD – Baseline SLD) / Baseline SLD) * 100%
Non-Target Lesion Assessment
Non-target lesions are those not selected as target lesions. Their assessment is generally qualitative:
- Present: Indicates the presence of non-target lesions.
- Absent: Indicates the absence of non-target lesions.
- Indeterminable: Indicates that non-target lesions cannot be assessed reliably.
Progression of non-target lesions is defined as unequivocal progression of existing non-target lesions.
New Lesion Assessment
This is a binary assessment:
- Absent: No new lesions are identified.
- Present: One or more new lesions are identified.
The appearance of any new lesion automatically signifies Progressive Disease (PD).
Overall Response Determination
The final RECIST response category (CR, PR, SD, PD) is determined by combining the target lesion changes, non-target lesion status, and new lesion status according to specific rules.
Variables Table
RECIST 1.1 Variables
| Variable |
Meaning |
Unit |
Typical Range |
| Longest Diameter (LD) |
The longest measurable diameter of a target lesion. |
mm |
≥ 10 mm (for target lesions) |
| Shortest Diameter (SD) |
The shortest measurable diameter of a target lesion. |
mm |
≥ 10 mm (for target lesions) |
| Sum of Longest Diameters (SLD) |
Sum of the longest diameters of all selected target lesions. |
mm |
≥ 10 mm (for target lesions) |
| Baseline SLD |
The SLD measured at the start of treatment. |
mm |
≥ 10 mm |
| Current SLD |
The SLD measured at the current assessment time point. |
mm |
≥ 0 mm |
| Percentage Change in SLD |
Relative change in SLD compared to baseline. |
% |
Varies (e.g., -100% to +∞%) |
| Non-Target Lesion Status |
Overall assessment of non-target lesions. |
Categorical |
Present, Absent, Indeterminable |
| New Lesion Status |
Indication of new lesion development. |
Categorical |
Present, Absent |
Practical Examples (Real-World Use Cases)
Example 1: Partial Response (PR)
A patient has a single target lesion with a baseline longest diameter of 30 mm. After treatment, the same lesion measures 20 mm.
- Inputs:
- Baseline Longest Diameter: 30.0 mm
- Current Longest Diameter: 20.0 mm
- Baseline Shortest Diameter: 20.0 mm
- Current Shortest Diameter: 15.0 mm
- Non-Target Lesion Status: Present
- New Lesion Status: Absent
- Calculations:
- Baseline SLD = 30.0 mm
- Current SLD = 20.0 mm
- Percentage Change = ((20.0 – 30.0) / 30.0) * 100% = -33.3%
- Results:
- Primary Result: Partial Response (PR)
- Target Lesion SLD Change: -33.3%
- Non-Target Lesion Assessment: Present
- New Lesion Assessment: Absent
- Interpretation: The target lesion has shrunk by more than 30%, and no new lesions have appeared. Non-target lesions remain present but haven't unequivocally progressed. This qualifies as a Partial Response.
Example 2: Progressive Disease (PD)
A patient has two target lesions. Lesion A has a baseline longest diameter of 15 mm. Lesion B has a baseline longest diameter of 12 mm. At follow-up, Lesion A measures 18 mm, and Lesion B measures 15 mm. A new lesion is also detected.
- Inputs:
- Baseline Longest Diameter (Lesion A): 15.0 mm
- Current Longest Diameter (Lesion A): 18.0 mm
- Baseline Longest Diameter (Lesion B): 12.0 mm
- Current Longest Diameter (Lesion B): 15.0 mm
- Baseline Shortest Diameter (Lesion A): 10.0 mm
- Current Shortest Diameter (Lesion A): 12.0 mm
- Baseline Shortest Diameter (Lesion B): 8.0 mm
- Current Shortest Diameter (Lesion B): 10.0 mm
- Non-Target Lesion Status: Absent
- New Lesion Status: Present
- Calculations:
- Baseline SLD = 15.0 mm + 12.0 mm = 27.0 mm
- Current SLD = 18.0 mm + 15.0 mm = 33.0 mm
- Percentage Change = ((33.0 – 27.0) / 27.0) * 100% = +22.2%
- Absolute Increase = 33.0 mm – 27.0 mm = 6.0 mm
- Results:
- Primary Result: Progressive Disease (PD)
- Target Lesion SLD Change: +22.2%
- Non-Target Lesion Assessment: Absent
- New Lesion Assessment: Present
- Interpretation: Although the percentage increase in SLD (22.2%) meets the criteria for PD, the appearance of a new lesion is sufficient on its own to classify the response as Progressive Disease. The absolute increase also meets the 5mm threshold.
How to Use This RECIST Calculator
Using the RECIST calculator is straightforward. Follow these steps to get an objective assessment of tumor response:
- Gather Baseline Measurements: Before starting treatment, identify and measure the longest and shortest diameters (in mm) of your selected target lesions. If you have multiple target lesions, sum their longest diameters to get the Baseline SLD.
- Gather Current Measurements: At the time of assessment (e.g., after a few cycles of therapy), measure the same target lesions again. Record the current longest and shortest diameters. Sum the current longest diameters to get the Current SLD.
- Assess Non-Target Lesions: Determine if any non-target lesions are present, absent, or indeterminable.
- Check for New Lesions: Confirm whether any new lesions have appeared since the baseline scan.
- Input Data: Enter the baseline and current longest diameters (and shortest if needed for context, though SLD is primary) into the respective fields of the calculator. Select the status for non-target and new lesions.
- Calculate: Click the "Calculate Response" button.
How to Read Results:
- Primary Result: This will display the overall RECIST response category (CR, PR, SD, or PD).
- Target Lesion SLD Change: Shows the percentage change in the sum of longest diameters. This is a key indicator for PR, SD, and PD.
- Baseline SLD & Current SLD: These values provide context for the percentage change.
- Non-Target & New Lesion Assessment: These confirm the status of other tumor indicators.
Decision-Making Guidance:
- CR/PR: Indicates a positive response to treatment. Treatment may continue.
- SD: Suggests the treatment is stabilizing the disease. Treatment may continue.
- PD: Indicates the disease is progressing. A change in treatment strategy is usually recommended.
Remember, this calculator is a tool to aid interpretation based on RECIST 1.1 guidelines. Clinical decisions should always be made by a qualified healthcare professional considering the full clinical picture.
Key Factors That Affect RECIST Results
Several factors influence the interpretation and application of RECIST criteria:
- Imaging Modality and Quality: The choice of imaging (CT, MRI, PET) and the quality of the scans are critical. Consistent protocols and high-resolution imaging are essential for accurate measurements. Differences in scanner technology or protocols between baseline and follow-up can introduce variability.
- Lesion Selection Consistency: It's crucial to consistently identify and measure the *same* target lesions at each assessment. If a lesion becomes difficult to delineate or is no longer measurable, it can complicate the SLD calculation. The selection of target lesions should be representative of the overall tumor burden.
- Measurement Variability: Even with standardized guidelines, there can be inter-observer variability (different radiologists measuring slightly different values) and intra-observer variability (the same radiologist measuring differently at different times). Using experienced radiologists and potentially independent central review helps mitigate this.
- Tumor Heterogeneity: Tumors are often heterogeneous, meaning different parts may respond differently. RECIST focuses on the longest diameter, which might not always reflect the overall change in tumor volume or viability, especially for irregularly shaped lesions.
- Treatment Effects vs. True Progression: Sometimes, treatment can cause inflammation or edema (swelling) in tumors, which might temporarily increase lesion size, mimicking progression (PD) according to RECIST criteria, even if the underlying tumor is responding. Distinguishing these effects is a common challenge.
- Definition of "New Lesion": Identifying a truly new lesion versus a small metastasis that was missed at baseline or a benign finding can be challenging. The appearance of any new lesion is a strong indicator of PD, making this assessment critical.
- Non-Target Lesion Assessment Subjectivity: While target lesions have precise measurements, non-target lesions are assessed more qualitatively. Determining "unequivocal progression" can sometimes be subjective and relies on experienced judgment.
- RECIST Version Used: Different versions of RECIST (e.g., 1.0 vs. 1.1) have slightly different criteria, particularly regarding lymph nodes and the definition of progression. Ensuring consistency in the version used is vital for comparing results over time or across studies.
Frequently Asked Questions (FAQ)
Q1: What is the minimum size for a lesion to be considered a target lesion in RECIST 1.1?
A1: For a lesion to be considered a target lesion, it must be ≥ 10 mm in longest diameter (LD) and clearly defined. For lymph nodes, short axis must be ≥ 15 mm.
Q2: Can RECIST be used for all types of cancer?
A2: RECIST was initially developed for solid tumors. While widely applied, its suitability can vary depending on the cancer type and its typical growth patterns. It's not designed for hematological malignancies (cancers of the blood).
Q3: What happens if a target lesion disappears completely?
A3: If a target lesion disappears, its diameter is considered 0 mm. This contributes to achieving a Partial Response (PR) or Complete Response (CR), provided other criteria are met.
Q4: How are lymph nodes assessed in RECIST 1.1?
A4: Lymph nodes can be target or non-target lesions. If targeted, the short axis diameter is measured. A short axis ≥ 15 mm is required for a lymph node to be considered a target lesion. A decrease to < 10 mm short axis means disappearance.
Q5: Does RECIST account for tumor shrinkage that isn't measurable by diameter (e.g., diffuse infiltration)?
A5: RECIST primarily relies on measurable diameters. Diffuse infiltration or other non-measurable disease is assessed as non-target lesion status. Significant worsening of non-target lesions can lead to a PD classification.
Q6: What is the difference between RECIST 1.0 and 1.1?
A6: RECIST 1.1 introduced several refinements, including a clearer definition of target lesion selection (max 5 total, max 2 per organ), updated criteria for lymph nodes (short axis ≥ 15 mm vs. ≥ 10 mm in 1.0), and specific rules for assessing progression based on the nadir (smallest SLD) SLD.
Q7: Can a patient have Stable Disease (SD) even if lesions grow slightly?
A7: Yes. To qualify for Progressive Disease (PD), the SLD must increase by at least 20% AND by an absolute value of at least 5 mm, relative to the smallest SLD recorded since treatment started. If the increase doesn't meet both conditions, it may remain Stable Disease (SD).
Q8: Is RECIST the only way to measure treatment response?
A8: No. RECIST is a standardized radiological endpoint. Other important endpoints include overall survival (OS), progression-free survival (PFS), duration of response (DoR), and patient-reported outcomes (quality of life). RECIST provides objective tumor burden data.
Related Tools and Internal Resources
var baselineLongestDiameterInput = document.getElementById("baselineLongestDiameter");
var currentLongestDiameterInput = document.getElementById("currentLongestDiameter");
var baselineShortestDiameterInput = document.getElementById("baselineShortestDiameter");
var currentShortestDiameterInput = document.getElementById("currentShortestDiameter");
var nonTargetLesionStatusSelect = document.getElementById("nonTargetLesionStatus");
var newLesionStatusSelect = document.getElementById("newLesionStatus");
var baselineLongestDiameterError = document.getElementById("baselineLongestDiameterError");
var currentLongestDiameterError = document.getElementById("currentLongestDiameterError");
var baselineShortestDiameterError = document.getElementById("baselineShortestDiameterError");
var currentShortestDiameterError = document.getElementById("currentShortestDiameterError");
var primaryResultDiv = document.getElementById("primary-result");
var currentSLDSPAN = document.getElementById("currentSLD");
var baselineSLDSPAN = document.getElementById("baselineSLD");
var percentChangeSLDSPAN = document.getElementById("percentChangeSLD");
var nonTargetAssessmentSpan = document.getElementById("nonTargetAssessment");
var newLesionAssessmentSpan = document.getElementById("newLesionAssessment");
var recistChart;
var chartContext;
function initializeChart() {
chartContext = document.getElementById("recistChart").getContext("2d");
recistChart = new Chart(chartContext, {
type: 'bar',
data: {
labels: ['Target Lesion SLD Change (%)', 'Overall Response'],
datasets: [{
label: 'SLD Change',
data: [0, 0],
backgroundColor: 'rgba(0, 74, 153, 0.6)',
borderColor: 'rgba(0, 74, 153, 1)',
borderWidth: 1
}, {
label: 'Response Category',
data: [0, 0], // Placeholder for categorical data visualization
backgroundColor: 'rgba(40, 167, 69, 0.6)', // Example color
borderColor: 'rgba(40, 167, 69, 1)',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: false,
ticks: {
callback: function(value) {
if (value === 0) return '0%';
if (value > 0) return '+' + value + '%';
return value + '%';
}
}
}
},
plugins: {
tooltip: {
callbacks: {
label: function(context) {
var label = context.dataset.label || ";
if (label) {
label += ': ';
}
if (context.parsed.y !== null) {
if (label.includes('SLD Change')) {
label += context.parsed.y + '%';
} else {
// Handle categorical label display if needed
label += context.raw;
}
}
return label;
}
}
},
legend: {
display: true
}
}
}
});
}
function updateChart(percentChange) {
if (!recistChart) {
initializeChart();
}
var responseCategory = getRECISTResponse(percentChange, nonTargetLesionStatusSelect.value, newLesionStatusSelect.value);
var responseValue;
switch(responseCategory) {
case 'CR': responseValue = 4; break; // Assign arbitrary values for visualization
case 'PR': responseValue = 3; break;
case 'SD': responseValue = 2; break;
case 'PD': responseValue = 1; break;
default: responseValue = 0;
}
recistChart.data.datasets[0].data = [percentChange, responseValue]; // SLD change in first dataset
recistChart.data.datasets[1].data = [0, responseValue]; // Response category in second dataset (adjust as needed for visualization)
// Update labels based on response
recistChart.data.labels = ['SLD Change (%)', 'Response'];
// Update dataset labels for clarity in legend/tooltip
recistChart.data.datasets[0].label = 'SLD Change (%)';
recistChart.data.datasets[1].label = 'Response Category';
recistChart.update();
}
function validateInput(inputElement, errorElement, minValue, maxValue) {
var value = parseFloat(inputElement.value);
var errorMsg = "";
if (isNaN(value)) {
errorMsg = "Please enter a valid number.";
} else if (value < 0) {
errorMsg = "Value cannot be negative.";
} else if (minValue !== undefined && value maxValue) {
errorMsg = "Value cannot exceed " + maxValue + ".";
}
if (errorMsg) {
errorElement.textContent = errorMsg;
errorElement.classList.add("visible");
inputElement.style.borderColor = "#dc3545";
return false;
} else {
errorElement.textContent = "";
errorElement.classList.remove("visible");
inputElement.style.borderColor = "#ddd";
return true;
}
}
function getRECISTResponse(percentChangeSLD, nonTargetStatus, newLesionStatus) {
var baselineSLD = parseFloat(document.getElementById("baselineLongestDiameter").value) + parseFloat(document.getElementById("baselineShortestDiameter").value); // Simplified for example, RECIST uses sum of LONGEST diameters
var currentSLD = parseFloat(document.getElementById("currentLongestDiameter").value) + parseFloat(document.getElementById("currentShortestDiameter").value); // Simplified for example
// RECIST 1.1 primarily uses the sum of LONGEST diameters for SLD calculation.
// The calculator inputs are simplified for demonstration.
// A more accurate implementation would require summing multiple target lesions if present.
// For this simplified calculator, we'll use the provided single lesion diameters as proxies for SLD.
var actualBaselineSLD = parseFloat(baselineLongestDiameterInput.value);
var actualCurrentSLD = parseFloat(currentLongestDiameterInput.value);
if (isNaN(actualBaselineSLD) || isNaN(actualCurrentSLD) || actualBaselineSLD 0 && change >= 20 && absoluteChange >= 5) {
return "PD";
}
// Check for partial response
if (change -30 && change < 20) {
// Also ensure absolute increase is less than 5mm if percentage is borderline
if (absoluteChange = 5mm, it might be PD even if percentage is < 20%
// This logic needs refinement based on exact RECIST 1.1 rules regarding nadir SLD.
// For simplicity here, we assume if it's not PR and not PD by the above rules, it's SD.
return "SD";
}
}
// If none of the above, default to PD or check non-target progression (simplified here)
if (nonTargetStatus === "present") {
// Simplified: Assume non-target progression implies PD if not CR/PR/SD
// A more robust check would involve specific criteria for non-target progression.
// For this calculator, if target lesions don't fit PR/SD and new lesions are absent,
// but non-target are present, it's often considered PD unless CR criteria met.
// Let's refine: If target lesions didn't shrink enough for PR, and didn't grow enough for PD,
// and non-target are present but not progressing, it's SD.
// If non-target lesions *are* progressing, it's PD.
// This calculator doesn't have explicit non-target progression input.
// We'll rely on the target lesion change and new lesion status primarily.
}
// Check for Complete Response (CR) – requires disappearance of target lesions AND non-target lesions
if (actualCurrentSLD === 0 && nonTargetStatus === "absent") {
return "CR";
}
// Default fallback if logic doesn't catch specific cases (should ideally not happen with comprehensive rules)
// If target lesions didn't meet PR criteria and didn't meet PD criteria, it's SD.
return "SD";
}
function calculateRECIST() {
var isValid = true;
// Validate Target Lesion Inputs
isValid &= validateInput(baselineLongestDiameterInput, baselineLongestDiameterError, 0);
isValid &= validateInput(currentLongestDiameterInput, currentLongestDiameterError, 0);
isValid &= validateInput(baselineShortestDiameterInput, baselineShortestDiameterError, 0);
isValid &= validateInput(currentShortestDiameterInput, currentShortestDiameterError, 0);
if (!isValid) {
primaryResultDiv.innerHTML = "– Please Correct Errors —
Invalid Input";
primaryResultDiv.style.backgroundColor = "#ffc107"; // Warning color
return;
}
// Use only longest diameters for SLD calculation as per RECIST 1.1
var baselineLD = parseFloat(baselineLongestDiameterInput.value);
var currentLD = parseFloat(currentLongestDiameterInput.value);
// Simplified calculation: Assuming only one target lesion for SLD.
// In reality, SLD is the sum of longest diameters of up to 5 target lesions.
var baselineSLD = baselineLD;
var currentSLD = currentLD;
var percentChangeSLD = 0;
var absoluteChange = 0;
if (baselineSLD > 0) {
percentChangeSLD = ((currentSLD – baselineSLD) / baselineSLD) * 100;
absoluteChange = currentSLD – baselineSLD;
} else if (currentSLD > 0) {
// Baseline was 0 or invalid, current is positive -> likely PD if new lesion or significant growth
percentChangeSLD = Infinity; // Represents significant increase from zero
absoluteChange = currentSLD;
} else {
// Both are 0 or invalid
percentChangeSLD = 0;
absoluteChange = 0;
}
var nonTargetStatus = nonTargetLesionStatusSelect.value;
var newLesionStatus = newLesionStatusSelect.value;
var responseCategory = getRECISTResponse(percentChangeSLD, nonTargetStatus, newLesionStatus);
// Update results display
baselineSLDSPAN.textContent = baselineSLD.toFixed(1);
currentSLDSPAN.textContent = currentSLD.toFixed(1);
if (percentChangeSLD === Infinity) {
percentChangeSLDSPAN.textContent = "N/A (Baseline <= 0)";
} else {
percentChangeSLDSPAN.textContent = percentChangeSLD.toFixed(1);
}
nonTargetAssessmentSpan.textContent = nonTargetStatus.charAt(0).toUpperCase() + nonTargetStatus.slice(1);
newLesionAssessmentSpan.textContent = newLesionStatus.charAt(0).toUpperCase() + newLesionStatus.slice(1);
primaryResultDiv.textContent = responseCategory;
primaryResultDiv.style.backgroundColor = "#28a745"; // Default to success color
primaryResultDiv.querySelector('span').textContent = "RECIST Response Category";
// Adjust primary result styling based on category
switch(responseCategory) {
case 'CR':
primaryResultDiv.style.backgroundColor = "#17a2b8"; // Info color for CR
break;
case 'PR':
primaryResultDiv.style.backgroundColor = "#28a745"; // Success color for PR
break;
case 'SD':
primaryResultDiv.style.backgroundColor = "#ffc107"; // Warning color for SD
break;
case 'PD':
primaryResultDiv.style.backgroundColor = "#dc3545"; // Danger color for PD
break;
default: // Invalid input or calculation error
primaryResultDiv.style.backgroundColor = "#6c757d"; // Secondary color
primaryResultDiv.querySelector('span').textContent = "Calculation Error";
break;
}
// Update the chart
updateChart(percentChangeSLD);
}
function resetForm() {
document.getElementById("recist-calculator-form").reset();
// Reset spans and primary result
baselineSLDSPAN.textContent = "–";
currentSLDSPAN.textContent = "–";
percentChangeSLDSPAN.textContent = "–";
nonTargetAssessmentSpan.textContent = "–";
newLesionAssessmentSpan.textContent = "–";
primaryResultDiv.textContent = "– Awaiting Input –";
primaryResultDiv.style.backgroundColor = "#6c757d"; // Reset to default grey
primaryResultDiv.querySelector('span').textContent = "RECIST Response Category";
// Clear errors
var errorElements = document.querySelectorAll(".error-message");
for (var i = 0; i < errorElements.length; i++) {
errorElements[i].textContent = "";
errorElements[i].classList.remove("visible");
}
var inputElements = document.querySelectorAll(".input-group input, .input-group select");
for (var i = 0; i < inputElements.length; i++) {
inputElements[i].style.borderColor = "#ddd";
}
// Reset chart data if chart exists
if (recistChart) {
recistChart.data.datasets[0].data = [0, 0];
recistChart.data.datasets[1].data = [0, 0];
recistChart.update();
}
}
function copyResults() {
var resultsText = "RECIST 1.1 Assessment Results:\n\n";
resultsText += "Overall Response: " + primaryResultDiv.textContent.trim() + "\n";
resultsText += "Target Lesion Sum of Diameters (SLD): " + currentSLDSPAN.textContent + " mm\n";
resultsText += "Baseline Target Lesion Sum of Diameters (SLD): " + baselineSLDSPAN.textContent + " mm\n";
resultsText += "Percentage Change in SLD: " + percentChangeSLDSPAN.textContent + " %\n";
resultsText += "Non-Target Lesion Assessment: " + nonTargetAssessmentSpan.textContent + "\n";
resultsText += "New Lesion Assessment: " + newLesionAssessmentSpan.textContent + "\n\n";
resultsText += "Key Assumptions:\n";
resultsText += "- Based on RECIST 1.1 criteria.\n";
resultsText += "- Calculation uses provided longest diameters as proxy for SLD (assumes single target lesion or sum).\n";
resultsText += "- Does not account for specific non-target lesion progression criteria beyond status.\n";
// Use a temporary textarea to copy text
var textArea = document.createElement("textarea");
textArea.value = resultsText;
textArea.style.position = "fixed";
textArea.style.left = "-9999px";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'Results copied!' : 'Copy failed!';
// Optionally show a temporary message to the user
var tempMsg = document.createElement('div');
tempMsg.textContent = msg;
tempMsg.style.position = 'fixed';
tempMsg.style.bottom = '10px';
tempMsg.style.left = '50%';
tempMsg.style.transform = 'translateX(-50%)';
tempMsg.style.backgroundColor = '#333';
tempMsg.style.color = 'white';
tempMsg.style.padding = '10px';
tempMsg.style.borderRadius = '5px';
tempMsg.style.zIndex = '10000';
document.body.appendChild(tempMsg);
setTimeout(function(){ document.body.removeChild(tempMsg); }, 2000);
} catch (err) {
console.error('Unable to copy results.', err);
// Optionally show error message
}
document.body.removeChild(textArea);
}
// Initial calculation on load if default values are present (optional)
// calculateRECIST();
// Initialize chart on page load
window.onload = function() {
initializeChart();
// Trigger initial calculation if default values are set or just to show initial state
calculateRECIST();
};