package LIMS::Local::GalliumTrial;
use Moose;
has data => (
is => 'ro',
isa => 'HashRef',
required => 1,
);
has test_codes => (
is => 'ro',
isa => 'HashRef',
lazy_build => 1,
);
__PACKAGE__->meta->make_immutable;
use Data::Dumper;
use LIMS::Local::Utils;
my $trim = sub { LIMS::Local::Utils::trim(@_) };
#===============================================================================
# regex's:
my $words_re = qr{\s?(\b\w+\b( \b\w+\b)?)}; # matches 1 or 2 words
my $igh_aso_re = qr{\s?(not evaluable|(mono|oligo|poly)clonal)}i;
my $biopsy_re = qr/
biopsy\:\s*(.*?)\.
/ix; # capture all between ':' and 1st full-stop
my $grade_re = qr{\b(grade\s\d\w?)\b}i; # lymphoma grade 1,2,3[ab]
#===============================================================================
sub get_lab_role {
my $self = shift;
my $clinical_details = $self->data->{clinical_details} || return 0;
my $result = $clinical_details =~ /referred from Kiel/i
? 'Adjudicator' : 'First Time Reviewer';
return $result;
}
# extract block ref + number of slides & blocks from external_ref:
sub get_external_reference {
my $self = shift;
my $exref = $self->data->{external_reference} or return 0;
# just capture 1st item of block_ref eg (125-16696) x20uss
my ($block_ref) = split /\sx(:?\d+)[spu]/, $exref; # warn $block_ref;
my ($unstained_slides) = $exref =~ /x(\d+)uss/; # warn $unstained_slides
my ($stained_slides) = $exref =~ /x(\d+)ss/; # warn $stained_slides
my ($blocks) = $exref =~ /x(\d+)p/; # warn $blocks;
my $slides = do {
no warnings 'uninitialized';
$unstained_slides + $stained_slides;
}; # warn Dumper [$block_ref, $slides, $blocks];
my %h = (
block_id => &$trim($block_ref),
slides => $slides || 0,
blocks => $blocks || 0,
);
return \%h;
}
sub get_rna_results {
my $self = shift;
my $result = $self->data->{molecular_summary} || return 0;
my %h = ();
if ( $result =~ /RNA volume\:(.*)ul/ ) { # warn $1
$h{rna_volume} = &$trim($1);
}
if ( $result =~ /RNA concentration\:(.*)ng/ ) { # warn $1;
$h{rna_concentration} = &$trim($1);
}
if ( $result =~ /OD260\/280\:\s?(\d*\.\d+)/ ) { # warn $1;
$h{rna_purity} = $1;
}
if ( $result =~ /RNA sections\:(.*)micron/ ) { # warn $1
$h{rna_sections} = &$trim($1);
} # warn Dumper [@{$vars}{qw(rna_volume rna_concentration rna_purity rna_sections)}];
return \%h;
}
sub get_igh_pcr {
my $self = shift;
my $result = $self->data->{molecular_summary} || return 0;
my %h = ();
if ( $result =~ /IgH-ASO assay\:$words_re/ ) { # warn $1;
$h{igh_pcr_assay} = &$trim($1);
}
if ( $result =~ /IgH-ASO result\:$igh_aso_re/ ) { # warn $1;
$h{igh_pcr_result} = lc &$trim($1);
}
if ( $result =~ /IgH-ASO bp length\:\s?(\d+)/ ) { # warn $1;
$h{igh_pcr_bp_length} = $1;
}
if ( $result =~ /IgH-ASO comment\:(.*)/ ) { # warn $1;
$h{igh_pcr_comment} = &$trim($1);
}
return \%h;
}
sub get_fish_break_apart_result {
my $self = shift;
my $col = shift;
my $val = $self->data->{$col} || return 0;
my $result = $val =~ /rearranged/
? 'Positive'
: $val eq 'failed'
? 'Not Evaluable' : 'Negative';
return $result;
}
sub get_fish_fusion_assay_result {
my $self = shift;
my $col = shift;
my $val = $self->data->{$col} || return 0;
my $result = $val =~ /translocation/
? 'Positive'
: $val eq 'failed'
? 'Not Evaluable' : 'Negative';
return $result;
}
sub get_biopsy_site {
my $self = shift; return 0; # pending
my ($site) = $self->data->{comment} =~ /$biopsy_re/;
return $site;
}
sub get_involvement_pattern {
my $self = shift;
return 0; # can't extract pattern of involvment from comment yet
}
sub get_lymphoma_grade {
my $self = shift;
my $icdo3 = $self->data->{icdo3} || return 0;
# extract grade - only if FL:
if ( $icdo3 =~ 9690 && $self->data->{comment} =~ /$grade_re/ ) {
return lc $1; # captures content of $grade_re
}
return 0;
}
sub get_sample_quality {
my $self = shift;
my $result = $self->data->{specimen_quality} || return 0;
$result =~ s/adequate/good/; # only using adequate & poor
return ucfirst $result;
}
sub get_morphology_comment {
my $self = shift;
my $comment = $self->data->{comment} || return 0;
$comment =~ s/[\n\r]/ /g; # replace new-lines with spaces
return $comment;
}
sub get_fish_summary {
my $self = shift;
return $self->data->{fish_summary} || 0;
}
sub is_retest_required {
my $self = shift;
my $diagnosis = $self->get_diagnosis || return 0;
return $diagnosis eq 'Inadequate sample' ? 'Yes' : 'No'; # inadequate needs re-test
}
sub get_diagnosis {
my $self = shift;
return $self->data->{diagnosis} || 0;
}
sub get_icdo3 {
my $self = shift;
return $self->data->{icdo3} || 0;
}
sub get_lymphoma_involvment {
my $self = shift;
return 100; # temp assessment
}
sub get_test_results {
my $self = shift;
my %SDL = %{ $self->test_codes }; # warn Dumper \%SDL;
my %h = ();
TEST: while ( my ($marker, $test_code) = each %SDL ) {
my $result = $self->data->{$marker} || next TEST;
$h{$test_code} = $result;
}; # warn Dumper \%h;
return \%h;
}
sub is_discrepant_diagnosis {
my $self = shift;
return 0; # pending
}
sub is_urgent_report {
my $self = shift;
return 0; # pending
}
sub is_urgent_block_return {
my $self = shift;
return 0; # pending
}
sub test_decodes { # reverses $self->test_codes
my $self = shift;
my $codes = $self->test_codes;
my %decodes = reverse %$codes;
return \%decodes;
}
# Quintiles test codes => HMDS test_name map:
sub _build_test_codes {
my $self = shift;
return {
cd3 => 'SDL2110',
cd5 => 'SDL2099',
cd10 => 'SDL2100',
cd20 => 'SDL2101',
cd23 => 'SDL2102',
cd79 => 'SDL2105',
bcl2 => 'SDL2103',
bcl6 => 'SDL2108',
irf4 => 'SDL2106',
ki67 => 'SDL2109',
foxp1 => 'SDL2107',
kappa => 'SDL2123',
lambda => 'SDL2134',
cyclin_d1 => 'SDL2104', # = bcl1
# BCL2 => 'SDL2115', # FISH - handled by get_fish_break_apart_result()
# BCL6 => 'SDL2116', # FISH - handled by get_fish_break_apart_result()
# BCL2_IgH => 'SDL2117', # FISH - handled by get_fish_fusion_assay_result()
};
}
1;