Beispiel #1
0
    def test_include_assessment_in_metric(self):
        pipeline = 'supervision'
        state_code = 'US_MO'
        assessment_type = StateAssessmentType.ORAS_COMMUNITY_SUPERVISION

        include_assessment = assessment_utils.include_assessment_in_metric(pipeline, state_code, assessment_type)

        self.assertTrue(include_assessment)

        assessment_type = StateAssessmentType.ORAS_COMMUNITY_SUPERVISION_SCREENING

        include_assessment = assessment_utils.include_assessment_in_metric(pipeline, state_code, assessment_type)

        self.assertTrue(include_assessment)
Beispiel #2
0
    def test_include_assessment_in_metric_unsupported_state_code(self):
        pipeline = 'supervision'
        state_code = 'US_XX'
        assessment_type = StateAssessmentType.ORAS_MISDEMEANOR_ASSESSMENT

        include_assessment = assessment_utils.include_assessment_in_metric(pipeline, state_code, assessment_type)

        self.assertFalse(include_assessment)
Beispiel #3
0
def characteristics_dict(person: StatePerson,
                         program_event: ProgramEvent) -> Dict[str, Any]:
    """Builds a dictionary that describes the characteristics of the person and event.

    Args:
        person: the StatePerson we are picking characteristics from
        program_event: the ProgramEvent we are picking characteristics from

    Returns:
        A dictionary populated with all relevant characteristics.
    """
    characteristics: Dict[str, Any] = {}

    event_date = program_event.event_date

    if isinstance(program_event, ProgramReferralEvent):
        if program_event.supervision_type:
            characteristics['supervision_type'] = program_event.supervision_type
        if program_event.assessment_score and program_event.assessment_type:
            assessment_bucket = assessment_score_bucket(
                assessment_score=program_event.assessment_score,
                assessment_level=None,
                assessment_type=program_event.assessment_type)

            if assessment_bucket and include_assessment_in_metric(
                    'program', program_event.state_code, program_event.assessment_type):
                characteristics['assessment_score_bucket'] = assessment_bucket
                characteristics['assessment_type'] = program_event.assessment_type

        if program_event.participation_status:
            characteristics['participation_status'] = program_event.participation_status
        if program_event.supervising_officer_external_id:
            characteristics['supervising_officer_external_id'] = program_event.supervising_officer_external_id
        if program_event.supervising_district_external_id:
            characteristics['supervising_district_external_id'] = program_event.supervising_district_external_id
    elif isinstance(program_event, ProgramParticipationEvent):
        characteristics['date_of_participation'] = event_date

        if program_event.supervision_type:
            characteristics['supervision_type'] = program_event.supervision_type
        if program_event.program_location_id:
            characteristics['program_location_id'] = program_event.program_location_id

    if program_event.program_id:
        characteristics['program_id'] = program_event.program_id

    characteristics = add_demographic_characteristics(characteristics, person, event_date)

    characteristics_with_person_details = characteristics_with_person_id_fields(
        characteristics, program_event.state_code, person, 'program')

    return characteristics_with_person_details
Beispiel #4
0
def characteristics_dict(person: StatePerson,
                         supervision_time_bucket: SupervisionTimeBucket,
                         metric_type: SupervisionMetricType) -> Dict[str, Any]:
    """Builds a dictionary that describes the characteristics of the person and supervision_time_bucket.

    Args:
        person: the StatePerson we are picking characteristics from
        supervision_time_bucket: the SupervisionTimeBucket we are picking characteristics from
        metric_type: The SupervisionMetricType provided determines which fields should be added to the characteristics
            dictionary

    Returns:
        A dictionary populated with all relevant characteristics.
    """
    characteristics: Dict[str, Any] = {}

    include_revocation_dimensions = _include_revocation_dimensions_for_metric(
        metric_type)
    include_assessment_dimensions = _include_assessment_dimensions_for_metric(
        metric_type)
    include_demographic_dimensions = _include_demographic_dimensions_for_metric(
        metric_type)
    include_person_level_dimensions = _include_person_level_dimensions_for_metric(
        metric_type)

    if (metric_type == SupervisionMetricType.POPULATION
            and isinstance(supervision_time_bucket,
                           (RevocationReturnSupervisionTimeBucket,
                            NonRevocationReturnSupervisionTimeBucket))):
        if supervision_time_bucket.most_severe_violation_type:
            characteristics[
                'most_severe_violation_type'] = supervision_time_bucket.most_severe_violation_type
        if supervision_time_bucket.most_severe_violation_type_subtype:
            characteristics['most_severe_violation_type_subtype'] = \
                supervision_time_bucket.most_severe_violation_type_subtype
        if supervision_time_bucket.response_count is not None:
            characteristics[
                'response_count'] = supervision_time_bucket.response_count

    if include_revocation_dimensions and \
            isinstance(supervision_time_bucket,
                       RevocationReturnSupervisionTimeBucket):
        if supervision_time_bucket.revocation_type:
            characteristics[
                'revocation_type'] = supervision_time_bucket.revocation_type

        if supervision_time_bucket.source_violation_type:
            characteristics[
                'source_violation_type'] = supervision_time_bucket.source_violation_type

        if metric_type in [
                SupervisionMetricType.REVOCATION_ANALYSIS,
                SupervisionMetricType.REVOCATION_VIOLATION_TYPE_ANALYSIS
        ]:
            if supervision_time_bucket.most_severe_violation_type:
                characteristics[
                    'most_severe_violation_type'] = supervision_time_bucket.most_severe_violation_type

            if supervision_time_bucket.most_severe_violation_type_subtype:
                characteristics['most_severe_violation_type_subtype'] = \
                    supervision_time_bucket.most_severe_violation_type_subtype

            if metric_type in [SupervisionMetricType.REVOCATION_ANALYSIS]:
                if supervision_time_bucket.most_severe_response_decision:
                    characteristics['most_severe_response_decision'] = \
                        supervision_time_bucket.most_severe_response_decision

            if supervision_time_bucket.response_count is not None:
                characteristics[
                    'response_count'] = supervision_time_bucket.response_count

    if isinstance(supervision_time_bucket, SupervisionTerminationBucket):
        if supervision_time_bucket.termination_reason:
            characteristics[
                'termination_reason'] = supervision_time_bucket.termination_reason

    if supervision_time_bucket.supervision_type:
        characteristics[
            'supervision_type'] = supervision_time_bucket.supervision_type
    if supervision_time_bucket.case_type:
        characteristics['case_type'] = supervision_time_bucket.case_type

    if not include_revocation_dimensions and supervision_time_bucket.supervision_level:
        characteristics[
            'supervision_level'] = supervision_time_bucket.supervision_level

    if include_assessment_dimensions:
        # TODO(2853): Figure out more robust solution for not assessed people. Here we don't set assessment_type when
        #  someone is not assessed. This only works as desired because BQ doesn't rely on assessment_type at all.
        characteristics['assessment_score_bucket'] = 'NOT_ASSESSED'
        if supervision_time_bucket.assessment_score and supervision_time_bucket.assessment_type:
            assessment_bucket = assessment_score_bucket(
                supervision_time_bucket.assessment_score,
                supervision_time_bucket.assessment_level,
                supervision_time_bucket.assessment_type)

            if assessment_bucket and include_assessment_in_metric(
                    'supervision', supervision_time_bucket.state_code,
                    supervision_time_bucket.assessment_type):
                characteristics['assessment_score_bucket'] = assessment_bucket
                characteristics[
                    'assessment_type'] = supervision_time_bucket.assessment_type
    if supervision_time_bucket.supervising_officer_external_id:
        characteristics[
            'supervising_officer_external_id'] = supervision_time_bucket.supervising_officer_external_id

    if supervision_time_bucket.supervising_district_external_id:
        characteristics[
            'supervising_district_external_id'] = supervision_time_bucket.supervising_district_external_id

    if isinstance(supervision_time_bucket,
                  RevocationReturnSupervisionTimeBucket):
        event_date = supervision_time_bucket.revocation_admission_date
    elif isinstance(supervision_time_bucket, SupervisionTerminationBucket):
        event_date = supervision_time_bucket.termination_date
    else:
        year = supervision_time_bucket.year
        month = supervision_time_bucket.month

        event_date = date(year, month, 1)

    if include_demographic_dimensions:
        characteristics = add_demographic_characteristics(
            characteristics, person, event_date)

    if include_person_level_dimensions:
        characteristics = characteristics_with_person_id_fields(
            characteristics, person, 'supervision')

        if not include_revocation_dimensions and supervision_time_bucket.supervision_level_raw_text:
            characteristics['supervision_level_raw_text'] = \
                supervision_time_bucket.supervision_level_raw_text

        if metric_type == SupervisionMetricType.POPULATION:
            if isinstance(supervision_time_bucket,
                          (RevocationReturnSupervisionTimeBucket,
                           NonRevocationReturnSupervisionTimeBucket)):
                characteristics['is_on_supervision_last_day_of_month'] = \
                    supervision_time_bucket.is_on_supervision_last_day_of_month

        if metric_type == SupervisionMetricType.REVOCATION_ANALYSIS:
            if isinstance(supervision_time_bucket, RevocationReturnSupervisionTimeBucket) \
                    and supervision_time_bucket.violation_history_description:
                characteristics['violation_history_description'] = \
                    supervision_time_bucket.violation_history_description

        if include_revocation_dimensions and isinstance(
                supervision_time_bucket,
                RevocationReturnSupervisionTimeBucket):
            characteristics['revocation_admission_date'] = \
                supervision_time_bucket.revocation_admission_date

        if metric_type == SupervisionMetricType.ASSESSMENT_CHANGE:
            if isinstance(supervision_time_bucket, SupervisionTerminationBucket) \
                    and supervision_time_bucket.termination_date:
                characteristics[
                    'termination_date'] = supervision_time_bucket.termination_date

    return characteristics
def characteristic_combinations(person: StatePerson,
                                supervision_time_bucket: SupervisionTimeBucket,
                                inclusions: Dict[str, bool],
                                metric_type: SupervisionMetricType) -> \
        List[Dict[str, Any]]:
    """Calculates all supervision metric combinations.

    Returns the list of all combinations of the metric characteristics, of all sizes, given the StatePerson and
    SupervisionTimeBucket. That is, this returns a list of dictionaries where each dictionary is a combination of 0
    to n unique elements of characteristics applicable to the given person and supervision_time_bucket.

    Args:
        person: the StatePerson we are picking characteristics from
        supervision_time_bucket: the SupervisionTimeBucket we are picking characteristics from
        inclusions: A dictionary containing the following keys that correspond
            to characteristic dimensions:
                - age_bucket
                - ethnicity
                - gender
                - race
            Where the values are boolean flags indicating whether to include
            the dimension in the calculations.
        metric_type: The SupervisionMetricType provided determines which fields should be added to the characteristics
            dictionary

    Returns:
        A list of dictionaries containing all unique combinations of
        characteristics.
    """
    characteristics: Dict[str, Any] = {}

    include_revocation_dimensions = _include_revocation_dimensions_for_metric(
        metric_type)
    include_assessment_dimensions = _include_assessment_dimensions_for_metric(
        metric_type)
    include_person_level_dimensions = _include_person_level_dimensions_for_metric(
        metric_type)

    if (metric_type == SupervisionMetricType.POPULATION
            and isinstance(supervision_time_bucket,
                           (RevocationReturnSupervisionTimeBucket,
                            NonRevocationReturnSupervisionTimeBucket))):
        if supervision_time_bucket.most_severe_violation_type:
            characteristics[
                'most_severe_violation_type'] = supervision_time_bucket.most_severe_violation_type
        if supervision_time_bucket.most_severe_violation_type_subtype:
            characteristics['most_severe_violation_type_subtype'] = \
                supervision_time_bucket.most_severe_violation_type_subtype
        if supervision_time_bucket.response_count is not None:
            characteristics[
                'response_count'] = supervision_time_bucket.response_count

    if include_revocation_dimensions and \
            isinstance(supervision_time_bucket,
                       RevocationReturnSupervisionTimeBucket):
        if supervision_time_bucket.revocation_type:
            characteristics[
                'revocation_type'] = supervision_time_bucket.revocation_type

        if supervision_time_bucket.source_violation_type:
            characteristics[
                'source_violation_type'] = supervision_time_bucket.source_violation_type

        if metric_type in [
                SupervisionMetricType.REVOCATION_ANALYSIS,
                SupervisionMetricType.REVOCATION_VIOLATION_TYPE_ANALYSIS
        ]:
            if supervision_time_bucket.most_severe_violation_type:
                characteristics[
                    'most_severe_violation_type'] = supervision_time_bucket.most_severe_violation_type

            if supervision_time_bucket.most_severe_violation_type_subtype:
                characteristics['most_severe_violation_type_subtype'] = \
                    supervision_time_bucket.most_severe_violation_type_subtype

            if metric_type in [SupervisionMetricType.REVOCATION_ANALYSIS]:
                if supervision_time_bucket.most_severe_response_decision:
                    characteristics['most_severe_response_decision'] = \
                        supervision_time_bucket.most_severe_response_decision

            if supervision_time_bucket.response_count is not None:
                characteristics[
                    'response_count'] = supervision_time_bucket.response_count

    if isinstance(supervision_time_bucket, SupervisionTerminationBucket):
        if supervision_time_bucket.termination_reason:
            characteristics[
                'termination_reason'] = supervision_time_bucket.termination_reason

    if supervision_time_bucket.supervision_type:
        characteristics[
            'supervision_type'] = supervision_time_bucket.supervision_type
    if supervision_time_bucket.case_type:
        characteristics['case_type'] = supervision_time_bucket.case_type

    if not include_revocation_dimensions and supervision_time_bucket.supervision_level:
        characteristics[
            'supervision_level'] = supervision_time_bucket.supervision_level

    if include_assessment_dimensions:
        # TODO(2853): Figure out more robust solution for not assessed people. Here we don't set assessment_type when
        #  someone is not assessed. This only works as desired because BQ doesn't rely on assessment_type at all.
        characteristics['assessment_score_bucket'] = 'NOT_ASSESSED'
        if supervision_time_bucket.assessment_score and supervision_time_bucket.assessment_type:
            assessment_bucket = assessment_score_bucket(
                supervision_time_bucket.assessment_score,
                supervision_time_bucket.assessment_level,
                supervision_time_bucket.assessment_type)

            if assessment_bucket and include_assessment_in_metric(
                    'supervision', supervision_time_bucket.state_code,
                    supervision_time_bucket.assessment_type):
                characteristics['assessment_score_bucket'] = assessment_bucket
                characteristics[
                    'assessment_type'] = supervision_time_bucket.assessment_type
    if supervision_time_bucket.supervising_officer_external_id:
        characteristics[
            'supervising_officer_external_id'] = supervision_time_bucket.supervising_officer_external_id

    if supervision_time_bucket.supervising_district_external_id:
        characteristics[
            'supervising_district_external_id'] = supervision_time_bucket.supervising_district_external_id
    if inclusions.get('age_bucket'):
        year = supervision_time_bucket.year
        month = supervision_time_bucket.month

        start_of_bucket = date(year, month, 1)
        entry_age = age_at_date(person, start_of_bucket)
        entry_age_bucket = age_bucket(entry_age)
        if entry_age_bucket is not None:
            characteristics['age_bucket'] = entry_age_bucket
    if inclusions.get('gender'):
        if person.gender is not None:
            characteristics['gender'] = person.gender

    if person.races or person.ethnicities:
        if inclusions.get('race'):
            races = person.races
        else:
            races = []

        if inclusions.get('ethnicity'):
            ethnicities = person.ethnicities
        else:
            ethnicities = []

        all_combinations = for_characteristics_races_ethnicities(
            races, ethnicities, characteristics)
    else:
        all_combinations = for_characteristics(characteristics)

    if include_person_level_dimensions:
        characteristics_with_person_details = characteristics_with_person_id_fields(
            characteristics, person, 'supervision')

        if not include_revocation_dimensions and supervision_time_bucket.supervision_level_raw_text:
            characteristics_with_person_details['supervision_level_raw_text'] = \
                supervision_time_bucket.supervision_level_raw_text

        if metric_type == SupervisionMetricType.POPULATION:
            if isinstance(supervision_time_bucket,
                          (RevocationReturnSupervisionTimeBucket,
                           NonRevocationReturnSupervisionTimeBucket)):
                characteristics_with_person_details['is_on_supervision_last_day_of_month'] = \
                    supervision_time_bucket.is_on_supervision_last_day_of_month

        if metric_type == SupervisionMetricType.REVOCATION_ANALYSIS:
            # Only include violation history descriptions on person-level metrics
            if isinstance(supervision_time_bucket, RevocationReturnSupervisionTimeBucket) \
                    and supervision_time_bucket.violation_history_description:
                characteristics_with_person_details['violation_history_description'] = \
                    supervision_time_bucket.violation_history_description

        all_combinations.append(characteristics_with_person_details)

    return all_combinations