gov.nih.nci.caintegrator.application.analysis.SurvivalCalculator.java Source code

Java tutorial

Introduction

Here is the source code for gov.nih.nci.caintegrator.application.analysis.SurvivalCalculator.java

Source

/**
 * Copyright 5AM Solutions Inc, ESAC, ScenPro & SAIC
 *
 * Distributed under the OSI-approved BSD 3-Clause License.
 * See http://ncip.github.com/caintegrator/LICENSE.txt for details.
 */
package gov.nih.nci.caintegrator.application.analysis;

import gov.nih.nci.caintegrator.application.kmplot.SubjectSurvivalData;
import gov.nih.nci.caintegrator.domain.annotation.DateAnnotationValue;
import gov.nih.nci.caintegrator.domain.annotation.NumericAnnotationValue;
import gov.nih.nci.caintegrator.domain.annotation.SurvivalValueDefinition;
import gov.nih.nci.caintegrator.domain.annotation.SurvivalValueTypeEnum;
import gov.nih.nci.caintegrator.domain.translational.StudySubjectAssignment;

import java.util.Calendar;

import org.apache.commons.lang3.StringUtils;

/**
 * This is a static utility class used for calculating survival values for a subject.
 */
public final class SurvivalCalculator {

    private static final int HOURS_IN_DAY = 24;
    private static final int DAYS_IN_WEEK = 7;
    private static final int MONTHS_IN_YEAR = 12;
    private static final double DAYS_IN_YEAR = 365.25;
    private static final double DAYS_IN_MONTH = DAYS_IN_YEAR / MONTHS_IN_YEAR;
    private static final long ONE_HOUR = 60 * 60 * 1000L;

    private SurvivalCalculator() {
    }

    /**
     * Creates survival data based on the definition and subject.
     * @param survivalValueDefinition to calculate survival data for.
     * @param subjectAssignment subject to calculate survival data.
     * @return survival data.
     */
    public static SubjectSurvivalData createSubjectSurvivalData(SurvivalValueDefinition survivalValueDefinition,
            StudySubjectAssignment subjectAssignment) {
        if (SurvivalValueTypeEnum.DATE.equals(survivalValueDefinition.getSurvivalValueType())) {
            return SurvivalCalculator.createDateBasedSurvivalData(survivalValueDefinition, subjectAssignment);
        }
        if (SurvivalValueTypeEnum.LENGTH_OF_TIME.equals(survivalValueDefinition.getSurvivalValueType())) {
            return SurvivalCalculator.createDurationBasedSurvivalData(survivalValueDefinition, subjectAssignment);
        }
        throw new IllegalStateException("Unknown survival value type.");
    }

    private static SubjectSurvivalData createDateBasedSurvivalData(SurvivalValueDefinition survivalValueDefinition,
            StudySubjectAssignment subjectAssignment) {

        DateAnnotationValue subjectSurvivalStartDate = subjectAssignment
                .getDateAnnotation(survivalValueDefinition.getSurvivalStartDate());
        DateAnnotationValue subjectDeathDate = subjectAssignment
                .getDateAnnotation(survivalValueDefinition.getDeathDate());
        DateAnnotationValue subjectLastFollowupDate = subjectAssignment
                .getDateAnnotation(survivalValueDefinition.getLastFollowupDate());
        Calendar calSubjectStartDate = Calendar.getInstance();
        Calendar calSubjectEndDate = Calendar.getInstance();
        if (subjectSurvivalStartDate != null && subjectSurvivalStartDate.getDateValue() != null) {
            calSubjectStartDate.setTime(subjectSurvivalStartDate.getDateValue());
        } else {
            return null;
        }
        Boolean censor = calculateEndDate(subjectDeathDate, subjectLastFollowupDate, calSubjectEndDate);
        if (censor == null) {
            return null;
        }
        int survivalLength = calculateSurvivalLength(survivalValueDefinition, calSubjectStartDate,
                calSubjectEndDate);
        return new SubjectSurvivalData(survivalLength, censor);
    }

    private static int calculateSurvivalLength(SurvivalValueDefinition survivalValueDefinition,
            Calendar calSubjectStartDate, Calendar calSubjectEndDate) {
        int survivalLength = 0;
        int daysBetween = daysBetween(calSubjectStartDate, calSubjectEndDate);
        switch (survivalValueDefinition.getSurvivalLengthUnits()) {
        case DAYS:
            survivalLength = daysBetween;
            break;
        case WEEKS:
            survivalLength = Math.round(daysBetween / DAYS_IN_WEEK);
            break;
        case MONTHS:
            survivalLength = (int) Math.round(daysBetween / DAYS_IN_MONTH);
            break;
        default:
            throw new IllegalStateException("Unknown survival length type.");
        }
        return survivalLength;
    }

    private static SubjectSurvivalData createDurationBasedSurvivalData(
            SurvivalValueDefinition survivalValueDefinition, StudySubjectAssignment subjectAssignment) {
        NumericAnnotationValue survivalLength = subjectAssignment
                .getNumericAnnotation(survivalValueDefinition.getSurvivalLength());
        if (survivalLength == null || survivalLength.getNumericValue() == null) {
            return null;
        }
        return new SubjectSurvivalData((int) Math.round(survivalLength.getNumericValue()),
                getCensorStatusForDurationBasedSurvival(survivalValueDefinition, subjectAssignment));
    }

    private static Boolean getCensorStatusForDurationBasedSurvival(SurvivalValueDefinition survivalValueDefinition,
            StudySubjectAssignment subjectAssignment) {
        Boolean censor = false;
        if (survivalValueDefinition.getSurvivalStatus() != null
                && !StringUtils.isBlank(survivalValueDefinition.getValueForCensored())) {
            String survivalStatus = subjectAssignment
                    .getAnnotationValueAsString(survivalValueDefinition.getSurvivalStatus());
            try {
                censor = Double.valueOf(survivalValueDefinition.getValueForCensored())
                        .equals(Double.valueOf(survivalStatus));
            } catch (Exception e) {
                censor = survivalValueDefinition.getValueForCensored().equals(survivalStatus);
            }
        }
        return censor;
    }

    private static Boolean calculateEndDate(DateAnnotationValue subjectDeathDate,
            DateAnnotationValue subjectLastFollowupDate, Calendar calSubjectEndDate) {
        Boolean censor = false;
        if ((subjectDeathDate == null || subjectDeathDate.getDateValue() == null)
                && (subjectLastFollowupDate != null && subjectLastFollowupDate.getDateValue() != null)) {
            calSubjectEndDate.setTime(subjectLastFollowupDate.getDateValue());
            censor = true;
        } else if ((subjectDeathDate != null && subjectDeathDate.getDateValue() != null)) {
            calSubjectEndDate.setTime(subjectDeathDate.getDateValue());
            censor = false;
        } else {
            return null;
        }
        return censor;
    }

    private static int daysBetween(Calendar startDate, Calendar endDate) {
        return Math.round(
                ((endDate.getTimeInMillis() - startDate.getTimeInMillis() + ONE_HOUR)) / (ONE_HOUR * HOURS_IN_DAY));
    }
}