コード例 #1
0
    def test_map_incarceration_combinations_two_releases_same_month(self):
        person = StatePerson.new_with_defaults(
            state_code="CA",
            person_id=12345,
            birthdate=date(1984, 8, 31),
            gender=Gender.FEMALE,
        )

        race = StatePersonRace.new_with_defaults(state_code="CA",
                                                 race=Race.WHITE)

        person.races = [race]

        ethnicity = StatePersonEthnicity.new_with_defaults(
            state_code="CA", ethnicity=Ethnicity.NOT_HISPANIC)

        person.ethnicities = [ethnicity]

        incarceration_events = [
            IncarcerationReleaseEvent(
                state_code="CA",
                event_date=date(2010, 3, 12),
                facility="FACILITY 33",
                county_of_residence=_COUNTY_OF_RESIDENCE,
            ),
            IncarcerationReleaseEvent(
                state_code="CA",
                event_date=date(2010, 3, 24),
                facility="FACILITY 33",
                county_of_residence=_COUNTY_OF_RESIDENCE,
            ),
        ]

        incarceration_combinations = calculator.map_incarceration_combinations(
            person=person,
            incarceration_events=incarceration_events,
            metric_inclusions=ALL_METRICS_INCLUSIONS_DICT,
            calculation_end_month=None,
            calculation_month_count=-1,
            person_metadata=_DEFAULT_PERSON_METADATA,
        )

        expected_combinations_count = expected_metric_combos_count(
            incarceration_events)

        self.assertEqual(expected_combinations_count,
                         len(incarceration_combinations))
        assert all(value == 1
                   for _combination, value in incarceration_combinations)
コード例 #2
0
    def test_map_incarceration_combinations_all_types(self):
        person = StatePerson.new_with_defaults(person_id=12345,
                                               birthdate=date(1984, 8, 31),
                                               gender=Gender.FEMALE)

        race = StatePersonRace.new_with_defaults(state_code='CA',
                                                 race=Race.WHITE)

        person.races = [race]

        ethnicity = StatePersonEthnicity.new_with_defaults(
            state_code='CA', ethnicity=Ethnicity.NOT_HISPANIC)

        person.ethnicities = [ethnicity]

        incarceration_events = [
            IncarcerationStayEvent(
                admission_reason=StateIncarcerationPeriodAdmissionReason.
                PAROLE_REVOCATION,
                admission_reason_raw_text='NEW_ADMISSION',
                supervision_type_at_admission=
                StateSupervisionPeriodSupervisionType.PAROLE,
                state_code='CA',
                event_date=date(2000, 3, 31),
                facility='SAN QUENTIN',
                county_of_residence=_COUNTY_OF_RESIDENCE,
                most_serious_offense_statute=_STATUTE,
            ),
            IncarcerationAdmissionEvent(
                state_code='CA',
                event_date=date(2000, 3, 12),
                facility='SAN QUENTIN',
                county_of_residence=_COUNTY_OF_RESIDENCE,
                admission_reason=AdmissionReason.PAROLE_REVOCATION,
                supervision_type_at_admission=
                StateSupervisionPeriodSupervisionType.PAROLE,
                admission_reason_raw_text='PAROLE_REVOCATION',
                specialized_purpose_for_incarceration=
                StateSpecializedPurposeForIncarceration.TREATMENT_IN_PRISON),
            IncarcerationReleaseEvent(
                state_code='CA',
                event_date=date(2003, 4, 12),
                facility='SAN QUENTIN',
                county_of_residence=_COUNTY_OF_RESIDENCE,
            )
        ]

        incarceration_combinations = calculator.map_incarceration_combinations(
            person=person,
            incarceration_events=incarceration_events,
            inclusions=ALL_INCLUSIONS_DICT,
            calculation_month_limit=-1)

        expected_combinations_count = expected_metric_combos_count(
            person, incarceration_events, ALL_INCLUSIONS_DICT)

        self.assertEqual(expected_combinations_count,
                         len(incarceration_combinations))
        assert all(value == 1
                   for _combination, value in incarceration_combinations)
コード例 #3
0
def release_event_for_period(
        incarceration_sentences: List[StateIncarcerationSentence],
        supervision_sentences: List[StateSupervisionSentence],
        incarceration_period: StateIncarcerationPeriod,
        county_of_residence: Optional[str]
) -> Optional[IncarcerationReleaseEvent]:
    """Returns an IncarcerationReleaseEvent if this incarceration period represents an release from incarceration."""
    release_date = incarceration_period.release_date
    release_reason = incarceration_period.release_reason
    purpose_for_incarceration = incarceration_period.specialized_purpose_for_incarceration

    if release_date and release_reason:
        supervision_type_at_release = get_post_incarceration_supervision_type(
            incarceration_sentences, supervision_sentences,
            incarceration_period)

        return IncarcerationReleaseEvent(
            state_code=incarceration_period.state_code,
            event_date=release_date,
            facility=incarceration_period.facility,
            release_reason=release_reason,
            release_reason_raw_text=incarceration_period.
            release_reason_raw_text,
            purpose_for_incarceration=purpose_for_incarceration,
            county_of_residence=county_of_residence,
            supervision_type_at_release=supervision_type_at_release)

    return None
コード例 #4
0
def release_event_for_period(
    incarceration_sentences: List[StateIncarcerationSentence],
    supervision_sentences: List[StateSupervisionSentence],
    incarceration_period: StateIncarcerationPeriod,
    county_of_residence: Optional[str],
) -> Optional[IncarcerationReleaseEvent]:
    """Returns an IncarcerationReleaseEvent if this incarceration period represents an release from incarceration."""
    release_date = incarceration_period.release_date
    release_reason = incarceration_period.release_reason
    purpose_for_incarceration = (
        incarceration_period.specialized_purpose_for_incarceration)

    supervision_type_at_admission = get_pre_incarceration_supervision_type(
        incarceration_sentences, supervision_sentences, incarceration_period)

    admission_reason = None
    if incarceration_period.admission_reason:
        admission_reason = state_specific_incarceration_admission_reason_override(
            incarceration_period.state_code,
            incarceration_period.admission_reason,
            supervision_type_at_admission,
        )

    if release_date and release_reason:
        supervision_type_at_release = get_post_incarceration_supervision_type(
            incarceration_sentences, supervision_sentences,
            incarceration_period)

        total_days_incarcerated = None

        if incarceration_period.admission_date:
            total_days_incarcerated = (
                release_date - incarceration_period.admission_date).days

            if total_days_incarcerated < 0:
                logging.warning(
                    "release_date before admission_date on incarceration period: %s",
                    incarceration_period,
                )
                total_days_incarcerated = 0

        return IncarcerationReleaseEvent(
            state_code=incarceration_period.state_code,
            event_date=release_date,
            facility=incarceration_period.facility,
            release_reason=release_reason,
            release_reason_raw_text=incarceration_period.
            release_reason_raw_text,
            purpose_for_incarceration=purpose_for_incarceration,
            county_of_residence=county_of_residence,
            supervision_type_at_release=supervision_type_at_release,
            admission_reason=admission_reason,
            total_days_incarcerated=total_days_incarcerated,
        )

    return None
コード例 #5
0
ファイル: pipeline_test.py プロジェクト: Leo-Ryu/pulse-data
    def testCalculateIncarcerationMetricCombinations(self):
        """Tests the CalculateIncarcerationMetricCombinations DoFn."""
        fake_person = StatePerson.new_with_defaults(
            person_id=123,
            gender=Gender.MALE,
            birthdate=date(1970, 1, 1),
            residency_status=ResidencyStatus.PERMANENT)

        incarceration_events = [
            IncarcerationAdmissionEvent(
                state_code='US_XX',
                event_date=date(2001, 3, 16),
                facility='SAN QUENTIN',
                county_of_residence='county_of_residence',
                admission_reason=StateIncarcerationPeriodAdmissionReason.
                PROBATION_REVOCATION),
            IncarcerationReleaseEvent(
                state_code='US_XX',
                event_date=date(2002, 5, 26),
                facility='SAN QUENTIN',
                county_of_residence='county_of_residence',
                release_reason=StateIncarcerationPeriodReleaseReason.
                SENTENCE_SERVED)
        ]

        # One metric per methodology for each event
        expected_metric_count = 2

        expected_combination_counts = \
            {'admissions': expected_metric_count,
             'releases': expected_metric_count}

        test_pipeline = TestPipeline()

        inputs = [(self.fake_person_id, {
            'person_events': [(fake_person, incarceration_events)],
            'person_metadata': [self.person_metadata]
        })]

        output = (test_pipeline
                  | beam.Create(inputs)
                  | beam.ParDo(ExtractPersonEventsMetadata())
                  | 'Calculate Incarceration Metrics' >> beam.ParDo(
                      pipeline.CalculateIncarcerationMetricCombinations(),
                      None, -1, ALL_METRICS_INCLUSIONS_DICT))

        assert_that(
            output,
            AssertMatchers.count_combinations(expected_combination_counts),
            'Assert number of metrics is expected value')

        test_pipeline.run()
コード例 #6
0
    def test_map_incarceration_combinations_relevant_periods(self):
        person = StatePerson.new_with_defaults(person_id=12345,
                                               birthdate=date(1984, 8, 31),
                                               gender=Gender.FEMALE)

        race = StatePersonRace.new_with_defaults(state_code='CA',
                                                 race=Race.WHITE)

        person.races = [race]

        ethnicity = StatePersonEthnicity.new_with_defaults(
            state_code='CA', ethnicity=Ethnicity.NOT_HISPANIC)

        person.ethnicities = [ethnicity]

        incarceration_events = [
            IncarcerationAdmissionEvent(
                state_code='CA',
                event_date=date(2010, 10, 2),
                facility='SAN QUENTIN',
                county_of_residence=_COUNTY_OF_RESIDENCE,
            ),
            IncarcerationReleaseEvent(
                state_code='CA',
                event_date=date(2010, 10, 19),
                facility='SAN QUENTIN',
                county_of_residence=_COUNTY_OF_RESIDENCE,
            )
        ]

        incarceration_combinations = calculator.map_incarceration_combinations(
            person=person,
            incarceration_events=incarceration_events,
            inclusions=ALL_INCLUSIONS_DICT,
            calculation_month_limit=-1)

        expected_combinations_count = expected_metric_combos_count(
            person, incarceration_events, ALL_INCLUSIONS_DICT,
            len(calculator_utils.METRIC_PERIOD_MONTHS),
            len(calculator_utils.METRIC_PERIOD_MONTHS))

        self.assertEqual(expected_combinations_count,
                         len(incarceration_combinations))
        assert all(value == 1
                   for _combination, value in incarceration_combinations)

        for combo, _ in incarceration_combinations:
            assert combo.get('year') == 2010
コード例 #7
0
def release_event_for_period(
        incarceration_period: StateIncarcerationPeriod,
        county_of_residence: Optional[str]) -> Optional[IncarcerationReleaseEvent]:
    """Returns an IncarcerationReleaseEvent if this incarceration period represents an release from incarceration."""

    release_date = incarceration_period.release_date
    release_reason = incarceration_period.release_reason
    incarceration_type = incarceration_period.incarceration_type

    if release_date and release_reason and \
            incarceration_type == StateIncarcerationType.STATE_PRISON:
        return IncarcerationReleaseEvent(
            state_code=incarceration_period.state_code,
            event_date=release_date,
            facility=incarceration_period.facility,
            release_reason=release_reason,
            county_of_residence=county_of_residence,
        )

    return None
コード例 #8
0
def release_event_for_period(
        incarceration_period: StateIncarcerationPeriod,
        county_of_residence: Optional[str]
) -> Optional[IncarcerationReleaseEvent]:
    """Returns an IncarcerationReleaseEvent if this incarceration period represents an release from incarceration."""

    release_date = incarceration_period.release_date
    release_reason = incarceration_period.release_reason
    purpose_for_incarceration = incarceration_period.specialized_purpose_for_incarceration

    if release_date and release_reason:
        return IncarcerationReleaseEvent(
            state_code=incarceration_period.state_code,
            event_date=release_date,
            facility=incarceration_period.facility,
            release_reason=release_reason,
            release_reason_raw_text=incarceration_period.
            release_reason_raw_text,
            purpose_for_incarceration=purpose_for_incarceration,
            county_of_residence=county_of_residence,
        )

    return None
コード例 #9
0
ファイル: pipeline_test.py プロジェクト: Leo-Ryu/pulse-data
    def testClassifyIncarcerationEvents(self):
        """Tests the ClassifyIncarcerationEvents DoFn."""
        fake_person_id = 12345

        fake_person = StatePerson.new_with_defaults(
            state_code='US_XX',
            person_id=fake_person_id,
            gender=Gender.MALE,
            birthdate=date(1970, 1, 1),
            residency_status=ResidencyStatus.PERMANENT)

        incarceration_period = StateIncarcerationPeriod.new_with_defaults(
            incarceration_period_id=1111,
            incarceration_type=StateIncarcerationType.STATE_PRISON,
            status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY,
            state_code='TX',
            facility='PRISON XX',
            admission_date=date(2010, 11, 20),
            admission_reason=StateIncarcerationPeriodAdmissionReason.
            PROBATION_REVOCATION,
            release_date=date(2010, 11, 21),
            release_reason=StateIncarcerationPeriodReleaseReason.
            SENTENCE_SERVED,
            specialized_purpose_for_incarceration=
            StateSpecializedPurposeForIncarceration.PAROLE_BOARD_HOLD)

        incarceration_sentence = StateIncarcerationSentence.new_with_defaults(
            incarceration_sentence_id=123,
            incarceration_periods=[incarceration_period],
            start_date=date(2009, 2, 9),
            charges=[
                StateCharge.new_with_defaults(ncic_code='5699',
                                              statute='30A123',
                                              offense_date=date(2009, 1, 9))
            ])

        sentence_group = StateSentenceGroup.new_with_defaults(
            sentence_group_id=123,
            incarceration_sentences=[incarceration_sentence])

        incarceration_sentence.sentence_group = sentence_group

        incarceration_period.incarceration_sentences = [incarceration_sentence]

        fake_person_id_to_county_query_result = [{
            'person_id':
            fake_person_id,
            'county_of_residence':
            _COUNTY_OF_RESIDENCE
        }]

        fake_incarceration_period_judicial_district_association_result = \
            {'person_id': fake_person_id, 'incarceration_period_id': 123, 'judicial_district_code': 'NW'}

        incarceration_events = [
            IncarcerationStayEvent(
                admission_reason=incarceration_period.admission_reason,
                admission_reason_raw_text=incarceration_period.
                admission_reason_raw_text,
                supervision_type_at_admission=
                StateSupervisionPeriodSupervisionType.PROBATION,
                state_code=incarceration_period.state_code,
                event_date=incarceration_period.admission_date,
                facility=incarceration_period.facility,
                county_of_residence=_COUNTY_OF_RESIDENCE,
                most_serious_offense_ncic_code='5699',
                most_serious_offense_statute='30A123',
                specialized_purpose_for_incarceration=
                StateSpecializedPurposeForIncarceration.PAROLE_BOARD_HOLD),
            IncarcerationAdmissionEvent(
                state_code=incarceration_period.state_code,
                event_date=incarceration_period.admission_date,
                facility=incarceration_period.facility,
                county_of_residence=_COUNTY_OF_RESIDENCE,
                admission_reason=incarceration_period.admission_reason,
                admission_reason_raw_text=incarceration_period.
                admission_reason_raw_text,
                supervision_type_at_admission=
                StateSupervisionPeriodSupervisionType.PROBATION,
                specialized_purpose_for_incarceration=
                StateSpecializedPurposeForIncarceration.PAROLE_BOARD_HOLD),
            IncarcerationReleaseEvent(
                state_code=incarceration_period.state_code,
                event_date=incarceration_period.release_date,
                facility=incarceration_period.facility,
                county_of_residence=_COUNTY_OF_RESIDENCE,
                release_reason=incarceration_period.release_reason,
                admission_reason=incarceration_period.admission_reason,
                total_days_incarcerated=(
                    incarceration_period.release_date -
                    incarceration_period.admission_date).days,
                purpose_for_incarceration=
                StateSpecializedPurposeForIncarceration.PAROLE_BOARD_HOLD)
        ]

        correct_output = [(fake_person_id, (fake_person, incarceration_events))
                          ]

        test_pipeline = TestPipeline()

        person_id_to_county_kv = (
            test_pipeline
            | "Read person id to county associations from BigQuery" >>
            beam.Create(fake_person_id_to_county_query_result)
            |
            "Convert to KV" >> beam.ParDo(ConvertDictToKVTuple(), 'person_id'))

        person_entities = {
            'person': [fake_person],
            'sentence_groups': [sentence_group],
            'incarceration_period_judicial_district_association':
            [fake_incarceration_period_judicial_district_association_result]
        }

        output = (test_pipeline
                  | beam.Create([(fake_person_id, person_entities)])
                  | 'Identify Incarceration Events' >> beam.ParDo(
                      pipeline.ClassifyIncarcerationEvents(),
                      AsDict(person_id_to_county_kv)))

        assert_that(output, equal_to(correct_output))

        test_pipeline.run()
コード例 #10
0
    def testCalculateIncarcerationMetricCombinations(self):
        """Tests the CalculateIncarcerationMetricCombinations DoFn."""
        fake_person = StatePerson.new_with_defaults(
            person_id=123,
            gender=Gender.MALE,
            birthdate=date(1970, 1, 1),
            residency_status=ResidencyStatus.PERMANENT)

        incarceration_events = [
            IncarcerationAdmissionEvent(
                state_code='CA',
                event_date=date(2001, 3, 16),
                facility='SAN QUENTIN',
                county_of_residence='county_of_residence',
                admission_reason=StateIncarcerationPeriodAdmissionReason.
                PROBATION_REVOCATION),
            IncarcerationReleaseEvent(
                state_code='CA',
                event_date=date(2002, 5, 26),
                facility='SAN QUENTIN',
                county_of_residence='county_of_residence',
                release_reason=StateIncarcerationPeriodReleaseReason.
                SENTENCE_SERVED)
        ]

        # Get the number of combinations of person-event characteristics.
        num_combinations = len(
            calculator.characteristic_combinations(
                fake_person, incarceration_events[0], ALL_INCLUSIONS_DICT,
                IncarcerationMetricType.POPULATION))
        assert num_combinations > 0

        expected_metric_count = num_combinations * 2

        expected_admission_combination_counts = \
            {'admissions': expected_metric_count}

        expected_releases_combination_counts = \
            {'releases': expected_metric_count}

        test_pipeline = TestPipeline()

        output = (
            test_pipeline
            | beam.Create([(fake_person, incarceration_events)])
            | 'Calculate Incarceration Metrics' >> beam.ParDo(
                pipeline.CalculateIncarcerationMetricCombinations(), -1,
                ALL_INCLUSIONS_DICT).with_outputs('admissions', 'releases'))

        assert_that(
            output.admissions,
            AssertMatchers.count_combinations(
                expected_admission_combination_counts),
            'Assert number of admission metrics is expected value')

        assert_that(
            output.releases,
            AssertMatchers.count_combinations(
                expected_releases_combination_counts),
            'Assert number of release metrics is expected value')

        test_pipeline.run()
コード例 #11
0
ファイル: pipeline_test.py プロジェクト: jazzPouls/pulse-data
    def testCalculateIncarcerationMetricCombinations(self):
        """Tests the CalculateIncarcerationMetricCombinations DoFn."""
        fake_person = StatePerson.new_with_defaults(
            state_code="US_XX",
            person_id=123,
            gender=Gender.MALE,
            birthdate=date(1970, 1, 1),
            residency_status=ResidencyStatus.PERMANENT,
        )

        incarceration_events = [
            IncarcerationAdmissionEvent(
                state_code="US_XX",
                event_date=date(2001, 3, 16),
                facility="SAN QUENTIN",
                county_of_residence="county_of_residence",
                admission_reason=StateIncarcerationPeriodAdmissionReason.
                PROBATION_REVOCATION,
            ),
            IncarcerationReleaseEvent(
                state_code="US_XX",
                event_date=date(2002, 5, 26),
                facility="SAN QUENTIN",
                county_of_residence="county_of_residence",
                release_reason=StateIncarcerationPeriodReleaseReason.
                SENTENCE_SERVED,
            ),
        ]

        expected_metric_count = 1

        expected_combination_counts = {
            "admissions": expected_metric_count,
            "releases": expected_metric_count,
        }

        test_pipeline = TestPipeline()

        inputs = [(
            self.fake_person_id,
            {
                "person_events": [(fake_person, incarceration_events)],
                "person_metadata": [self.person_metadata],
            },
        )]

        output = (test_pipeline
                  | beam.Create(inputs)
                  | beam.ParDo(ExtractPersonEventsMetadata())
                  | "Calculate Incarceration Metrics" >> beam.ParDo(
                      pipeline.CalculateIncarcerationMetricCombinations(),
                      None,
                      -1,
                      ALL_METRICS_INCLUSIONS_DICT,
                  ))

        assert_that(
            output,
            AssertMatchers.count_combinations(expected_combination_counts),
            "Assert number of metrics is expected value",
        )

        test_pipeline.run()
コード例 #12
0
ファイル: pipeline_test.py プロジェクト: jazzPouls/pulse-data
    def testClassifyIncarcerationEvents(self):
        """Tests the ClassifyIncarcerationEvents DoFn."""
        fake_person_id = 12345

        fake_person = StatePerson.new_with_defaults(
            state_code="US_XX",
            person_id=fake_person_id,
            gender=Gender.MALE,
            birthdate=date(1970, 1, 1),
            residency_status=ResidencyStatus.PERMANENT,
        )

        incarceration_period = StateIncarcerationPeriod.new_with_defaults(
            incarceration_period_id=1111,
            incarceration_type=StateIncarcerationType.STATE_PRISON,
            status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY,
            state_code="TX",
            facility="PRISON XX",
            admission_date=date(2010, 11, 20),
            admission_reason=StateIncarcerationPeriodAdmissionReason.
            PROBATION_REVOCATION,
            release_date=date(2010, 11, 21),
            release_reason=StateIncarcerationPeriodReleaseReason.
            SENTENCE_SERVED,
            specialized_purpose_for_incarceration=
            StateSpecializedPurposeForIncarceration.PAROLE_BOARD_HOLD,
        )

        incarceration_sentence = StateIncarcerationSentence.new_with_defaults(
            state_code="US_XX",
            incarceration_sentence_id=123,
            status=StateSentenceStatus.PRESENT_WITHOUT_INFO,
            incarceration_periods=[incarceration_period],
            start_date=date(2009, 2, 9),
            charges=[
                StateCharge.new_with_defaults(
                    state_code="US_XX",
                    status=ChargeStatus.PRESENT_WITHOUT_INFO,
                    ncic_code="5699",
                    statute="30A123",
                    offense_date=date(2009, 1, 9),
                )
            ],
        )

        sentence_group = StateSentenceGroup.new_with_defaults(
            state_code="US_XX",
            status=StateSentenceStatus.PRESENT_WITHOUT_INFO,
            sentence_group_id=123,
            incarceration_sentences=[incarceration_sentence],
        )

        incarceration_sentence.sentence_group = sentence_group

        incarceration_period.incarceration_sentences = [incarceration_sentence]

        fake_person_id_to_county_query_result = {
            "person_id": fake_person_id,
            "county_of_residence": _COUNTY_OF_RESIDENCE,
        }

        fake_incarceration_period_judicial_district_association_result = {
            "person_id": fake_person_id,
            "incarceration_period_id": 123,
            "judicial_district_code": "NW",
        }

        incarceration_events = [
            IncarcerationStayEvent(
                admission_reason=incarceration_period.admission_reason,
                admission_reason_raw_text=incarceration_period.
                admission_reason_raw_text,
                supervision_type_at_admission=
                StateSupervisionPeriodSupervisionType.PROBATION,
                state_code=incarceration_period.state_code,
                event_date=incarceration_period.admission_date,
                facility=incarceration_period.facility,
                county_of_residence=_COUNTY_OF_RESIDENCE,
                most_serious_offense_ncic_code="5699",
                most_serious_offense_statute="30A123",
                specialized_purpose_for_incarceration=
                StateSpecializedPurposeForIncarceration.PAROLE_BOARD_HOLD,
            ),
            IncarcerationAdmissionEvent(
                state_code=incarceration_period.state_code,
                event_date=incarceration_period.admission_date,
                facility=incarceration_period.facility,
                county_of_residence=_COUNTY_OF_RESIDENCE,
                admission_reason=incarceration_period.admission_reason,
                admission_reason_raw_text=incarceration_period.
                admission_reason_raw_text,
                supervision_type_at_admission=
                StateSupervisionPeriodSupervisionType.PROBATION,
                specialized_purpose_for_incarceration=
                StateSpecializedPurposeForIncarceration.PAROLE_BOARD_HOLD,
            ),
            IncarcerationReleaseEvent(
                state_code=incarceration_period.state_code,
                event_date=incarceration_period.release_date,
                facility=incarceration_period.facility,
                county_of_residence=_COUNTY_OF_RESIDENCE,
                release_reason=incarceration_period.release_reason,
                admission_reason=incarceration_period.admission_reason,
                total_days_incarcerated=(
                    incarceration_period.release_date -
                    incarceration_period.admission_date).days,
                purpose_for_incarceration=
                StateSpecializedPurposeForIncarceration.PAROLE_BOARD_HOLD,
            ),
        ]

        correct_output = [(fake_person_id, (fake_person, incarceration_events))
                          ]

        test_pipeline = TestPipeline()

        person_entities = {
            "person": [fake_person],
            "sentence_groups": [sentence_group],
            "incarceration_period_judicial_district_association":
            [fake_incarceration_period_judicial_district_association_result],
            "persons_to_recent_county_of_residence":
            [fake_person_id_to_county_query_result],
        }

        output = (test_pipeline
                  | beam.Create([(fake_person_id, person_entities)])
                  | "Identify Incarceration Events" >> beam.ParDo(
                      pipeline.ClassifyIncarcerationEvents()))

        assert_that(output, equal_to(correct_output))

        test_pipeline.run()