Process ratings to assign status to notes and optionally compute rater properties. Accepts prescoringNoteModelOutput and prescoringRaterModelOutput as args (fields on scoringArgs) which are the outputs of the prescore() function. These are used to initialize the final scoring. It
(self, scoringArgs: FinalScoringArgs)
| 364 | ) |
| 365 | |
| 366 | def score_final(self, scoringArgs: FinalScoringArgs) -> ModelResult: |
| 367 | """ |
| 368 | Process ratings to assign status to notes and optionally compute rater properties. |
| 369 | |
| 370 | Accepts prescoringNoteModelOutput and prescoringRaterModelOutput as args (fields on scoringArgs) |
| 371 | which are the outputs of the prescore() function. These are used to initialize the final scoring. |
| 372 | It filters the prescoring output to only include the rows relevant to this scorer, based on the |
| 373 | c.scorerNameKey field of those dataframes. |
| 374 | """ |
| 375 | torch.set_num_threads(self._threads) |
| 376 | logger.info( |
| 377 | f"score_final: Torch intra-op parallelism for {self.get_name()} set to: {torch.get_num_threads()}" |
| 378 | ) |
| 379 | |
| 380 | # Filter unfiltered params to just params for this scorer (with copy). |
| 381 | # Avoid editing the dataframe in FinalScoringArgs, which is shared across scorers. |
| 382 | prescoringNoteModelOutput = scoringArgs.prescoringNoteModelOutput[ |
| 383 | scoringArgs.prescoringNoteModelOutput[c.scorerNameKey] == self.get_prescoring_name() |
| 384 | ].drop(columns=c.scorerNameKey, inplace=False) |
| 385 | |
| 386 | if scoringArgs.prescoringRaterModelOutput is None: |
| 387 | return self._return_empty_final_scores() |
| 388 | prescoringRaterModelOutput = scoringArgs.prescoringRaterModelOutput[ |
| 389 | scoringArgs.prescoringRaterModelOutput[c.scorerNameKey] == self.get_prescoring_name() |
| 390 | ].drop(columns=c.scorerNameKey, inplace=False) |
| 391 | |
| 392 | if len(prescoringRaterModelOutput) == 0: |
| 393 | logger.info( |
| 394 | f"Scorer {self.get_prescoring_name()} has no raters in prescoringRaterModelOutput; returning empty scores from final scoring." |
| 395 | ) |
| 396 | return self._return_empty_final_scores() |
| 397 | |
| 398 | if self.get_prescoring_name() not in scoringArgs.prescoringMetaOutput.metaScorerOutput: |
| 399 | logger.info( |
| 400 | f"Scorer {self.get_prescoring_name()} not found in prescoringMetaOutput; returning empty scores from final scoring." |
| 401 | ) |
| 402 | return self._return_empty_final_scores() |
| 403 | prescoringMetaScorerOutput = scoringArgs.prescoringMetaOutput.metaScorerOutput[ |
| 404 | self.get_prescoring_name() |
| 405 | ] |
| 406 | |
| 407 | # Filter raw input |
| 408 | with self.time_block("Filter input"): |
| 409 | ratings, noteStatusHistory = self._filter_input( |
| 410 | scoringArgs.noteTopics, |
| 411 | scoringArgs.ratings, |
| 412 | scoringArgs.noteStatusHistory, |
| 413 | scoringArgs.userEnrollment, |
| 414 | ) |
| 415 | # If there are no ratings left after filtering, then return empty dataframes. |
| 416 | if len(ratings) == 0: |
| 417 | logger.info( |
| 418 | f"No rating left after filtering for Scorer {self.get_name()}, returning empty dataframes." |
| 419 | ) |
| 420 | return self._return_empty_final_scores() |
| 421 | |
| 422 | try: |
| 423 | noteScores, userScores = self._score_notes_and_users( |
no test coverage detected