File Coverage

lib/Convert/Pheno/BFF.pm
Criterion Covered Total %
statement 58 59 98.3
branch 21 26 80.7
condition n/a
subroutine 8 8 100.0
pod 0 1 0.0
total 87 94 92.5


line stmt bran cond sub pod time code
1             package Convert::Pheno::BFF;
2              
3 6     6   49 use strict;
  6         10  
  6         204  
4 6     6   43 use warnings;
  6         12  
  6         151  
5 6     6   49 use autodie;
  6         19  
  6         34  
6 6     6   33753 use feature qw(say);
  6         18  
  6         414  
7 6     6   41 use Convert::Pheno::Mapping;
  6         24  
  6         793  
8 6     6   47 use Convert::Pheno::PXF;
  6         12  
  6         295  
9 6     6   36 use Exporter 'import';
  6         17  
  6         4385  
10             our @EXPORT = qw(do_bff2pxf);
11              
12             #############
13             #############
14             # BFF2PXF #
15             #############
16             #############
17              
18             sub do_bff2pxf {
19              
20 583     583 0 756 my ( $self, $bff ) = @_;
21              
22             # Premature return
23 583 50       1260 return unless defined($bff);
24              
25             # Define defaults
26 583         720 my $default_timestamp = '1900-01-01T00:00:00Z';
27              
28             #########################################
29             # START MAPPING TO PHENOPACKET V2 TERMS #
30             #########################################
31              
32             # We need to shuffle a bit some Beacon v2 properties to be Phenopacket compliant
33             # Order of terms (not alphabetical) taken from:
34             # - https://phenopacket-schema.readthedocs.io/en/latest/phenopacket.html
35              
36 583         580 my $pxf;
37              
38             # ==
39             # id
40             # ==
41              
42 583 100       1239 $pxf->{id} = $self->{test} ? undef : 'phenopacket_id.' . randStr(8);
43              
44             # =======
45             # subject
46             # =======
47              
48             $pxf->{subject} = {
49             id => $bff->{id},
50              
51             #alternateIds => [],
52             #_age => $bff->{info}{age}
53             #timeAtLastEncounter => {},
54             vitalStatus => { status => 'ALIVE' }, #["UNKNOWN_STATUS", "ALIVE", "DECEASED"]
55 583         2394 sex => uc( $bff->{sex}{label} ),
56              
57             #taxonomy => {} ;
58             #_age => $bff->{info}{age}
59             };
60              
61             # Miscellanea
62 583         991 for (qw(dateOfBirth)) {
63 583 100       1710 $pxf->{subject}{$_} = $bff->{info}{$_} if exists $bff->{info}{$_};
64             }
65              
66             # karyotypicSex
67             $pxf->{subject}{karyotypicSex} = $bff->{karyotypicSex}
68 583 50       965 if exists $bff->{karyotypicSex};
69              
70             # ===================
71             # phenotypicFeatures
72             # ===================
73              
74             $pxf->{phenotypicFeatures} = [
75             map {
76             {
77             type => delete $_->{featureType},
78             excluded => delete $_->{excluded}
79              
80             #_notes => $_->{notes}
81             }
82 243         942 } @{ $bff->{phenotypicFeatures} }
  124         241  
83             ]
84 583 100       1018 if defined $bff->{phenotypicFeatures};
85              
86             # ============
87             # measurements
88             # ============
89 583 100       930 if ( defined $bff->{measures} ) {
90 83         109 $pxf->{measurements} = []; # Initialize as an empty array reference
91              
92 83         92 for my $measure ( @{ $bff->{measures} } ) {
  83         135  
93              
94             # Check if measurementValue hash contain the typedQuantities key
95             my $has_typedQuantities =
96 1147 50       2059 exists $measure->{measurementValue}{typedQuantities} ? 1 : 0;
97              
98             # Construct the hash
99 1147         1872 my $result = { assay => $measure->{assayCode} };
100              
101             # Add the complexValue key if typedQuantities was found
102 1147 50       1322 if ($has_typedQuantities) {
103 0         0 $result->{complexValue} = $measure->{measurementValue};
104             }
105             else {
106 1147         1252 $result->{value} = $measure->{measurementValue};
107              
108             }
109              
110             # Push the resulting hash onto the pxf measurements array
111 1147         1046 push @{ $pxf->{measurements} }, $result;
  1147         1740  
112             }
113             }
114              
115             # ==========
116             # biosamples
117             # ==========
118              
119             # ===============
120             # interpretations
121             # ===============
122              
123             #$bff->{interpretation} = {};
124              
125             # ========
126             # diseases
127             # ========
128              
129             $pxf->{diseases} =
130 569         1454 [ map { { term => $_->{diseaseCode}, onset => $_->{ageOfOnset} } }
131 583         662 @{ $bff->{diseases} } ];
  583         1234  
132              
133             # ===============
134             # medicalActions
135             # ===============
136              
137             # **** procedures ****
138             my @procedures = map {
139             {
140             procedure => {
141             code => $_->{procedureCode},
142             performed => {
143             timestamp => exists $_->{dateOfProcedure}
144             ? _map2iso8601( $_->{dateOfProcedure} )
145 576 100       1531 : $default_timestamp
146             }
147             }
148             }
149 583         727 } @{ $bff->{interventionsOrProcedures} };
  583         1139  
150              
151             # **** treatments ****
152             my @treatments = map {
153             {
154             treatment => {
155             agent => $_->{treatmentCode},
156             routeOfAdministration => $_->{routeOfAdministration},
157             doseIntervals => $_->{doseIntervals}
158              
159             #performed => { timestamp => exists $_->{dateOfProcedure} ? $_->{dateOfProcedure} : undef}
160             }
161             }
162 583         840 } @{ $bff->{treatments} };
  300         1048  
  583         1420  
163              
164             # Load
165 583 100       1030 push @{ $pxf->{medicalActions} }, @procedures if @procedures;
  157         399  
166 583 100       859 push @{ $pxf->{medicalActions} }, @treatments if @treatments;
  48         157  
167              
168             # =====
169             # files
170             # =====
171              
172             # =========
173             # metaData
174             # =========
175              
176             # Depending on the origion (redcap) , _info and resources may exist
177             $pxf->{metaData} =
178             $self->{test} ? undef
179             : exists $bff->{info}{metaData} ? $bff->{info}{metaData}
180 583 50       1186 : get_metaData($self);
    100          
181              
182             # =========
183             # exposures
184             # =========
185              
186             # Can't be mapped as Sept-2023 from pxf-tools
187             # Message type "org.phenopackets.schema.v2.Phenopacket" has no field named "exposures" at "Phenopacket".
188             # Available Fields(except extensions): "['id', 'subject', 'phenotypicFeatures', 'measurements', 'biosamples', 'interpretations', 'diseases', 'medicalActions', 'files', 'metaData']" at line 22
189              
190             # $pxf->{exposures} =
191             #
192             # [
193             # map {
194             # {
195             # type => $_->{exposureCode},
196             # occurrence => { timestamp => $_->{date} }
197             # }
198             # } @{ $bff->{exposures} }
199             # ]
200             # if exists $bff->{exposures};
201              
202             #######################################
203             # END MAPPING TO PHENOPACKET V2 TERMS #
204             #######################################
205              
206 583         1355 return $pxf;
207             }
208              
209             1;