예제 #1
0
def should_include_in_release_cohort(
        status: StateIncarcerationPeriodStatus, release_date: Optional[date],
        release_reason: Optional[ReleaseReason],
        next_incarceration_period: Optional[StateIncarcerationPeriod]) -> bool:
    """Identifies whether a period of incarceration with the given features should be included in the release
    cohort."""
    # If the person is still in custody, there is no release to include in a cohort.
    if status == StateIncarcerationPeriodStatus.IN_CUSTODY:
        return False

    if not release_date:
        # If the person is not in custody, there should be a release_date.
        # This should not happen after validation. Throw error.
        raise ValueError("release_date is not set where it should be.")

    if not release_reason:
        # If there is no recorded release reason, then we cannot classify this as a valid release for the cohort
        return False

    if next_incarceration_period:
        time_range_release = DateRange.for_day(release_date)
        if DateRangeDiff(time_range_release,
                         next_incarceration_period.duration).overlapping_range:
            # If the release overlaps with the following incarceration period, this is not an actual release from
            # incarceration
            return False

        if next_incarceration_period.release_date and release_date == next_incarceration_period.release_date:
            # This release shares a release_date with the next incarceration period. Do not include this release.
            return False

    if release_reason in [ReleaseReason.DEATH, ReleaseReason.EXECUTION]:
        # If the person was released from this incarceration period because they died or were executed, do not include
        # them in the release cohort.
        return False
    if release_reason == ReleaseReason.ESCAPE:
        # If the person was released from this incarceration period because they escaped, do not include them in the
        # release cohort.
        return False
    if release_reason == ReleaseReason.RELEASED_FROM_TEMPORARY_CUSTODY:
        # If the person was released from a period of temporary custody, do not include them in the release_cohort.
        return False
    if release_reason == ReleaseReason.RELEASED_IN_ERROR:
        # If the person was released from this incarceration period due to an error, do not include them in the
        # release cohort.
        return False
    if release_reason == ReleaseReason.TRANSFER:
        # If the person was released from this incarceration period because they were transferred elsewhere, do not
        # include them in the release cohort.
        return False
    if release_reason == ReleaseReason.TRANSFERRED_OUT_OF_STATE:
        # Releases where the person has been transferred out of state don't really count as true releases.
        return False
    if release_reason == ReleaseReason.COURT_ORDER:
        # If the person was released from this incarceration period due to a court order, do not include them in the
        # release cohort.
        return False
    if release_reason in (ReleaseReason.EXTERNAL_UNKNOWN,
                          ReleaseReason.INTERNAL_UNKNOWN):
        # We do not have enough information to determine whether this release qualifies for inclusion in the release
        # cohort.
        return False
    if release_reason in (ReleaseReason.COMMUTED, ReleaseReason.COMPASSIONATE,
                          ReleaseReason.CONDITIONAL_RELEASE,
                          ReleaseReason.PARDONED,
                          ReleaseReason.RELEASED_FROM_ERRONEOUS_ADMISSION,
                          ReleaseReason.SENTENCE_SERVED,
                          ReleaseReason.VACATED):
        return True

    raise ValueError("Enum case not handled for "
                     "StateIncarcerationPeriodReleaseReason of type:"
                     f" {release_reason}.")
예제 #2
0
    @classmethod
    def get_or_default(cls, text: Optional[str]) -> 'SnapshotType':
        if text is None:
            return SnapshotType.DAY
        return cls(text)

    DAY = 'DAY'
    FIRST_DAY_OF_MONTH = 'FIRST_DAY_OF_MONTH'
    LAST_DAY_OF_MONTH = 'LAST_DAY_OF_MONTH'


SNAPSHOT_CONVERTERS: Dict[SnapshotType, DateRangeConverterType] = {
    SnapshotType.DAY:
    DateRange.for_day,
    SnapshotType.FIRST_DAY_OF_MONTH:
    lambda date: DateRange.for_day(first_day_of_month(date)),
    SnapshotType.LAST_DAY_OF_MONTH:
    lambda date: DateRange.for_day(last_day_of_month(date)),
}


class Metric:
    @property
    @abstractmethod
    def filters(self) -> List[Dimension]:
        """Any dimensions where the data only represents a subset of values for that dimension.

        For instance, a table for the population metric may only cover data for the prison population, not those on
        parole or probation. In that case filters would contain PopulationType.PRISON.
        """