File Coverage

lib/Convert/Pheno/OMOP.pm
Criterion Covered Total %
statement 116 141 82.2
branch 38 66 57.5
condition 2 3 66.6
subroutine 9 9 100.0
pod 0 2 0.0
total 165 221 74.6


line stmt bran cond sub pod time code
1             package Convert::Pheno::OMOP;
2              
3 6     6   44 use strict;
  6         11  
  6         180  
4 6     6   32 use warnings;
  6         13  
  6         139  
5 6     6   59 use autodie;
  6         11  
  6         59  
6 6     6   34091 use feature qw(say);
  6         17  
  6         635  
7 6     6   2936 use Convert::Pheno::Mapping;
  6         19  
  6         822  
8 6     6   52 use Exporter 'import';
  6         19  
  6         326  
9             our @EXPORT =
10             qw(do_omop2bff $omop_version $omop_main_table @omop_array_tables @omop_essential_tables @stream_ram_memory_tables);
11              
12 6     6   43 use constant DEVEL_MODE => 0;
  6         26  
  6         12863  
13              
14             our $omop_version = 'v5.4';
15             our $omop_main_table = {
16             'v5.4' => [
17             qw(
18             PERSON
19             OBSERVATION_PERIOD
20             VISIT_OCCURRENCE
21             VISIT_DETAIL
22             CONDITION_OCCURRENCE
23             DRUG_EXPOSURE
24             PROCEDURE_OCCURRENCE
25             DEVICE_EXPOSURE
26             MEASUREMENT
27             OBSERVATION
28             NOTE
29             NOTE_NLP
30             SPECIMEN
31             FACT_RELATIONSHIP
32             SURVEY_CONDUCT
33             )
34             ],
35             'v6' => [
36             qw(
37             PERSON
38             OBSERVATION_PERIOD
39             VISIT_OCCURRENCE
40             VISIT_DETAIL
41             CONDITION_OCCURRENCE
42             DRUG_EXPOSURE
43             PROCEDURE_OCCURRENCE
44             DEVICE_EXPOSURE
45             MEASUREMENT
46             OBSERVATION
47             DEATH
48             NOTE
49             NOTE_NLP
50             SPECIMEN
51             FACT_RELATIONSHIP
52             )
53             ]
54             };
55              
56             our @omop_array_tables = qw(
57             MEASUREMENT
58             OBSERVATION
59             CONDITION_OCCURRENCE
60             PROCEDURE_OCCURRENCE
61             DRUG_EXPOSURE
62             VISIT_OCCURRENCE
63             );
64              
65             our @omop_essential_tables = qw(
66             CONCEPT
67             CONDITION_OCCURRENCE
68             PERSON
69             PROCEDURE_OCCURRENCE
70             MEASUREMENT
71             OBSERVATION
72             DRUG_EXPOSURE
73             VISIT_OCCURRENCE
74             );
75              
76             our @stream_ram_memory_tables = qw/CONCEPT PERSON VISIT_OCCURRENCE/;
77              
78             ##############
79             ##############
80             # OMOP2BFF #
81             ##############
82             ##############
83              
84             sub do_omop2bff {
85              
86 69647     69647 0 93282 my ( $self, $participant ) = @_;
87              
88 69647         103724 my $ohdsi_dic = $self->{data_ohdsi_dic};
89 69647         100081 my $sth = $self->{sth};
90              
91             # Set default values
92 69647         89843 my $default_duration = 'P0Y';
93              
94             ####################################
95             # START MAPPING TO BEACON V2 TERMS #
96             ####################################
97 69647         82180 my $individual;
98              
99             # Get cursors for 1D terms
100 69647         82941 my $person = $participant->{PERSON};
101              
102             # $participant = input data
103             # $person = cursor to $participant->PERSON
104             # $individual = output data
105              
106             # ABOUT REQUIRED PROPERTIES
107             # 'id' and 'sex' are required properties in <individuals> entry type
108             # 'person_id' must exist at this point otherwise it would have not been created
109             # Premature return as undef
110 69647 100       142875 return unless defined $person->{gender_concept_id};
111              
112             # ========
113             # diseases
114             # ========
115              
116 68707         78773 my $table = 'CONDITION_OCCURRENCE';
117              
118             # Table CONDITION_OCCURRENCE
119             # 1 condition_concept_id
120             # 2 condition_end_date
121             # 3 condition_end_datetime
122             # 4 condition_occurrence_id
123             # 5 condition_source_concept_id
124             # 6 condition_source_value
125             # 7 condition_start_date
126             # 8 condition_start_datetime
127             # 9 condition_status_concept_id
128             # 10 condition_status_source_value
129             # 11 condition_type_concept_id
130             # 12 person_id
131             # 13 provider_id
132             # 14 stop_reason
133             # 15 visit_detail_id
134             # 16 visit_occurrence_id
135              
136 68707 100       121081 if ( defined $participant->{$table} ) {
137              
138 156         252 for my $field ( @{ $participant->{$table} } ) {
  156         478  
139 984         1022 my $disease;
140              
141             $disease->{ageOfOnset} = {
142             age => {
143             iso8601duration => find_age(
144              
145             #_birth_datetime => $person->{birth_datetime}, # Property not allowed
146             #_procedure_date => $field->{procedure_date}, # Property not allowed
147             {
148              
149             date => $field->{condition_start_date},
150             birth_day => $person->{birth_datetime}
151             }
152             )
153 984         7265 }
154             };
155              
156             $disease->{diseaseCode} = map2ohdsi(
157             {
158             ohdsi_dic => $ohdsi_dic,
159             concept_id => $field->{condition_concept_id},
160             self => $self
161             }
162 984 50       6382 ) if defined $field->{condition_concept_id};
163              
164             #$disease->{familyHistory} = convert2boolean(
165             # map2redcap_dict(
166             # {
167             # redcap_dict => $redcap_dict,
168             # participant => $participant,
169             # field => 'family_history'
170             # }
171             # )
172             #) if $participant->{family_history} ne '';
173              
174             # notes MUST be string
175             # _info (Autovivification)
176 984         2464 $disease->{_info}{$table}{OMOP_columns} = $field;
177              
178             #$disease->{severity} = undef;
179             $disease->{stage} = map2ohdsi(
180             {
181             ohdsi_dic => $ohdsi_dic,
182             concept_id => $field->{condition_status_concept_id},
183             self => $self
184              
185             }
186 984 50       5144 ) if defined $field->{condition_status_concept_id};
187              
188             # NB: PROVISIONAL
189             # Longitudinal data are not allowed yet in BFF/PXF
190 984 50       2182 if ( exists $self->{visit_occurrence} ) {
191             my $visit = map_omop_visit_occurrence(
192             {
193             person_id => $field->{person_id},
194             visit_occurrence_id => $field->{visit_occurrence_id},
195 984         7582 self => $self,
196             ohdsi_dic => $ohdsi_dic
197             }
198             );
199 984 100       2319 $disease->{_visit} = $visit if defined $visit;
200             }
201              
202 984         1108 push @{ $individual->{diseases} }, $disease;
  984         2882  
203             }
204             }
205              
206             # =========
207             # ethnicity
208             # =========
209              
210             $individual->{ethnicity} = map_ontology(
211             {
212             query => $person->{race_source_value}
213             , # not getting it from *_concept_id
214             column => 'label',
215             ontology => 'ncit',
216              
217             #ontology => 'ohdsi',
218             self => $self
219             }
220 68707 100       127401 ) if defined $person->{race_source_value};
221              
222             # =========
223             # exposures
224             # =========
225              
226             # 'observation_concept_id' => 37017711,
227             # 'observation_date' => '1945-05-25',
228             # 'observation_datetime' => '1945-05-25 00:00:00',
229             # 'observation_id' => 919,
230             # 'observation_source_concept_id' => 37017711,
231             # 'observation_source_value' => 714035009,
232             # 'observation_type_concept_id' => 38000280,
233             # 'person_id' => 1476,
234             # 'provider_id' => 0,
235             # 'qualifier_concept_id' => 0,
236             # 'qualifier_source_value' => undef,
237             # 'unit_concept_id' => 0,
238             # 'unit_source_value' => undef,
239             # 'value_as_concept_id' => 0,
240             # 'value_as_number' => '\\N',
241             # 'value_as_string' => undef,
242             # 'visit_detail_id' => 0,
243             # 'visit_occurrence_id' => 98529
244              
245             #**************************************************
246             # *** IMPORTANT ***
247             # We'll only process if exist in $self->{exposures};
248             #*************************************************
249             #
250 68707         89301 $table = 'OBSERVATION';
251              
252 68707 100       138062 if ( defined $participant->{$table} ) {
253              
254 108         135 for my $field ( @{ $participant->{$table} } ) {
  108         383  
255              
256             # Note that these changes with DEVEL_MODE affect phenotypicFeatures (also uses OBSERVATION)
257 158         190 $field->{observation_concept_id} = 35609831
258             if DEVEL_MODE; # Note that it affects
259             #$field->{value_as_number} = 10 if DEVEL_MODE;
260              
261             # NB: Values in key hashes are stringfied so make a copy to keep them as integer
262 158         631 my $field_observation_concept_id = $field->{observation_concept_id};
263             next
264 158 50       464 unless exists $self->{exposures}{$field_observation_concept_id};
265 0         0 my $exposure;
266              
267             $exposure->{ageAtExposure} = {
268             age => {
269             iso8601duration => find_age(
270              
271             {
272              
273             date => $field->{observation_date},
274             birth_day => $person->{birth_datetime}
275             }
276             )
277 0         0 }
278              
279             };
280              
281 0         0 $exposure->{date} = $field->{observation_date};
282 0         0 $exposure->{duration} = $default_duration;
283              
284             # _info
285 0         0 $exposure->{_info}{$table}{OMOP_columns} = $field;
286              
287             $exposure->{exposureCode} = map2ohdsi(
288             {
289             ohdsi_dic => $ohdsi_dic,
290             concept_id => $field->{observation_concept_id},
291             self => $self
292             }
293 0 0       0 ) if defined $field->{observation_concept_id};
294              
295             my $unit = map2ohdsi(
296             {
297             ohdsi_dic => $ohdsi_dic,
298             concept_id => $field->{unit_concept_id},
299 0         0 self => $self
300              
301             }
302             );
303              
304 0         0 $exposure->{unit} = $unit;
305             $exposure->{value} =
306             $field->{value_as_number} eq '\\N'
307             ? -1
308 0 0       0 : $field->{value_as_number} + 0;
309              
310             # NB: We do not include _visit in exposures
311              
312 0         0 push @{ $individual->{exposures} }, $exposure;
  0         0  
313             }
314             }
315              
316             # ================
317             # geographicOrigin
318             # ================
319              
320             $individual->{geographicOrigin} = map_ontology(
321             {
322             query => $person->{ethnicity_source_value},
323             column => 'label',
324             ontology => 'ncit',
325             self => $self
326             }
327 68707 100       127678 ) if defined $person->{ethnicity_source_value};
328              
329             # ==
330             # id
331             # ==
332              
333 68707         129723 $individual->{id} = $person->{person_id};
334              
335             # Forcing string w/o changing orig ref ($person)
336 68707         125743 $individual->{id} = qq/$individual->{id}/;
337              
338             # ====
339             # info
340             # ====
341              
342 68707         78816 $table = 'PERSON';
343              
344             # Table PERSON
345             # 1 birth_datetime
346             # 2 care_site_id
347             # 3 day_of_birth
348             # 4 ethnicity_concept_id
349             # 5 ethnicity_source_concept_id
350             # 6 ethnicity_source_value
351             # 7 gender_concept_id
352             # 8 gender_source_concept_id
353             # 9 gender_source_value
354             # 10 location_id
355             # 11 month_of_birth
356             # 12 person_id
357             # 13 person_source_value
358             # 14 provider_id
359             # 15 race_concept_id
360             # 16 race_source_concept_id
361             # 17 race_source_value
362             # 18 year_of_birth
363              
364             # info (Autovivification)
365 68707         139289 $individual->{info}{$table}{OMOP_columns} = $person;
366              
367             # Hard-coded $individual->{info}{dateOfBirth}
368             $individual->{info}{dateOfBirth} =
369 68707         154584 _map2iso8601( $person->{birth_datetime} );
370              
371             # =========================
372             # interventionsOrProcedures
373             # =========================
374              
375 68707         110256 $table = 'PROCEDURE_OCCURRENCE';
376              
377             # 1 modifier_concept_id
378             # 2 modifier_source_value
379             # 3 person_id
380             # 4 procedure_concept_id
381             # 5 procedure_date
382             # 6 procedure_datetime
383             # 7 procedure_occurrence_id
384             # 8 procedure_source_concept_id
385             # 9 procedure_source_value
386             # 10 procedure_type_concept_id
387             # 11 provider_id
388             # 12 quantity
389             # 13 visit_detail_id
390             # 14 visit_occurrence_id
391              
392 68707 100       129317 if ( defined $participant->{$table} ) {
393              
394 184         317 $individual->{interventionsOrProcedures} = [];
395              
396 184         260 for my $field ( @{ $participant->{$table} } ) {
  184         681  
397 866         901 my $intervention;
398              
399             $intervention->{ageAtProcedure} = {
400             age => {
401              
402             iso8601duration => find_age(
403              
404             #_birth_datetime => $person->{birth_datetime}, # Property not allowed
405             #_procedure_date => $field->{procedure_date}, # Property not allowed
406             {
407              
408             date => $field->{procedure_date},
409             birth_day => $person->{birth_datetime}
410             }
411             )
412 866         5448 }
413             };
414              
415             #$intervention->{bodySite} = undef;
416 866         2088 $intervention->{dateOfProcedure} = $field->{procedure_date};
417              
418             # _info (Autovivification)
419 866         1649 $intervention->{_info}{$table}{OMOP_columns} = $field;
420             $intervention->{procedureCode} = map2ohdsi(
421             {
422             ohdsi_dic => $ohdsi_dic,
423             concept_id => $field->{procedure_concept_id},
424             self => $self
425              
426             }
427 866 50       4392 ) if defined $field->{procedure_concept_id};
428              
429 866         1282 push @{ $individual->{interventionsOrProcedures} }, $intervention;
  866         2216  
430             }
431             }
432              
433             # =============
434             # karyotypicSex
435             # =============
436              
437             # $individual->{karyotypicSex} = undef;
438              
439             # ========
440             # measures
441             # ========
442              
443 68707         88023 $table = 'MEASUREMENT';
444              
445             # 1 measurement_concept_id
446             # 2 measurement_date
447             # 3 measurement_datetime
448             # 4 measurement_id
449             # 5 measurement_source_concept_id
450             # 6 measurement_source_value
451             # 7 measurement_time
452             # 8 measurement_type_concept_id
453             # 9 operator_concept_id
454             # 10 person_id
455             # 11 provider_id
456             # 12 range_high
457             # 13 range_low
458             # 14 unit_concept_id
459             # 15 unit_source_value
460             # 16 value_as_concept_id
461             # 17 value_as_number
462             # 18 value_source_value
463             # 19 visit_detail_id
464             # 20 visit_occurrence_id
465              
466             # Examples:
467              
468             # "measurement_concept_id" : 3006322,
469             # "measurement_date" : "1943-02-03",
470             # "measurement_datetime" : "1943-02-03 00:00:00",
471             # "measurement_id" : 9852,
472             # "measurement_source_concept_id" : 3006322,
473             # "measurement_source_value" : "8331-1",
474             # "measurement_time" : "1943-02-03",
475             # "measurement_type_concept_id" : 5001,
476             # "operator_concept_id" : 0,
477             # "person_id" : 929,
478             # "provider_id" : 0,
479             # "range_high" : "\\N",
480             # "range_low" : "\\N",
481             # "unit_concept_id" : 0,
482             # "unit_source_value" : null,
483             # "value_as_concept_id" : 0,
484             # "value_as_number" : "\\N",
485             # "value_source_value" : null,
486             # "visit_detail_id" : 0,
487             # "visit_occurrence_id" : 61837
488              
489 68707 100       118017 if ( defined $participant->{$table} ) {
490              
491 72         102 for my $field ( @{ $participant->{$table} } ) {
  72         290  
492              
493             # FAKE VALUES FOR DEBUG
494 208         203 $field->{unit_concept_id} = 18753 if DEVEL_MODE;
495 208         205 $field->{value_as_number} = 20 if DEVEL_MODE;
496 208         206 $field->{operator_concept_id} = 4172756 if DEVEL_MODE;
497              
498             # Only proceeding if we have actual values
499 208 50       1088 next if $field->{value_as_number} eq '\\N';
500              
501 0         0 my $measure;
502              
503             $measure->{assayCode} = map2ohdsi(
504             {
505             ohdsi_dic => $ohdsi_dic,
506             concept_id => $field->{measurement_concept_id},
507             self => $self
508             }
509 0 0       0 ) if defined $field->{measurement_concept_id};
510              
511 0         0 $measure->{date} = $field->{measurement_date};
512              
513             my $unit = map2ohdsi(
514             {
515             ohdsi_dic => $ohdsi_dic,
516             concept_id => $field->{unit_concept_id},
517 0         0 self => $self
518              
519             }
520             );
521              
522             # *** IMPORTANT ***
523             # We can get value_as_concept_id or as value_as_number
524             # NB: EUNOMIA always -- $field->{value_as_concept_id} = 0;
525 0         0 $field->{value_as_concept_id} = 18753 if DEVEL_MODE;
526              
527             $measure->{measurementValue} =
528             $field->{value_as_concept_id} ? map2ohdsi(
529             {
530             ohdsi_dic => $ohdsi_dic,
531             concept_id => $field->{value_as_concept_id},
532             self => $self
533             }
534             )
535             : {
536             quantity => {
537             unit => $unit,
538             value => $field->{value_as_number},
539             referenceRange => $field->{operator_concept_id}
540             ? map_operator_concept_id(
541             {
542             operator_concept_id =>
543             $field->{operator_concept_id},
544             value_as_number => $field->{value_as_number},
545 0 0       0 unit => $unit
    0          
546             }
547             )
548             : undef
549             }
550             };
551              
552             # notes MUST be string
553             # _info (Autovivification)
554 0         0 $measure->{_info}{$table}{OMOP_columns} = $field;
555             $measure->{observationMoment} = {
556             age => {
557             iso8601duration => find_age(
558             {
559             date => $field->{measurement_date},
560             birth_day => $person->{birth_datetime}
561             }
562             )
563 0         0 }
564             };
565 0         0 $measure->{procedure} = { procedureCode => $measure->{assayCode} };
566              
567             # NB: PROVISIONAL
568             # Longitudinal data are not allowed yet in BFF/PXF
569 0 0       0 if ( exists $self->{visit_occurrence} ) {
570             my $visit = map_omop_visit_occurrence(
571             {
572             person_id => $field->{person_id},
573             visit_occurrence_id => $field->{visit_occurrence_id},
574 0         0 self => $self,
575             ohdsi_dic => $ohdsi_dic
576             }
577             );
578 0 0       0 $measure->{_visit} = $visit if defined $visit;
579             }
580              
581 0         0 push @{ $individual->{measures} }, $measure;
  0         0  
582             }
583             }
584              
585             # =========
586             # pedigrees
587             # =========
588              
589             # ==================
590             # phenotypicFeatures
591             # ==================
592              
593 68707         83028 $table = 'OBSERVATION';
594              
595             # 'observation_concept_id' => 37017711,
596             # 'observation_date' => '1945-05-25',
597             # 'observation_datetime' => '1945-05-25 00:00:00',
598             # 'observation_id' => 919,
599             # 'observation_source_concept_id' => 37017711,
600             # 'observation_source_value' => 714035009,
601             # 'observation_type_concept_id' => 38000280,
602             # 'person_id' => 1476,
603             # 'provider_id' => 0,
604             # 'qualifier_concept_id' => 0,
605             # 'qualifier_source_value' => undef,
606             # 'unit_concept_id' => 0,
607             # 'unit_source_value' => undef,
608             # 'value_as_concept_id' => 0,
609             # 'value_as_number' => '\\N',
610             # 'value_as_string' => undef,
611             # 'visit_detail_id' => 0,
612             # 'visit_occurrence_id' => 98529
613              
614             # *** IMPORTANT ***
615             # We'll only process if not exist in $self->{exposures};
616              
617 68707 100       116984 if ( defined $participant->{$table} ) {
618              
619 108         262 $individual->{phenotypicFeatures} = [];
620              
621 108         151 for my $field ( @{ $participant->{$table} } ) {
  108         221  
622              
623             # NB: Values in key hashes are stringfied so make a copy to keep them as integer
624 158         237 my $field_observation_concept_id = $field->{observation_concept_id};
625             next
626 158 50       379 if exists $self->{exposures}{$field_observation_concept_id};
627              
628 158         206 my $phenotypicFeature;
629              
630             #$phenotypicFeature->{evidence} = undef;
631             #$phenotypicFeature->{excluded} = undef;
632             $phenotypicFeature->{featureType} = map2ohdsi(
633             {
634             ohdsi_dic => $ohdsi_dic,
635             concept_id => $field->{observation_concept_id},
636             self => $self
637              
638             }
639 158 50       727 ) if defined $field->{observation_concept_id};
640              
641             #$phenotypicFeature->{modifiers} = undef;
642              
643             # notes MUST be string
644             # _info (Autovivification)
645 158         422 $phenotypicFeature->{_info}{$table}{OMOP_columns} = $field;
646              
647             $phenotypicFeature->{onset} = {
648              
649             #_birth_datetime => $person->{birth_datetime}, # property not allowed
650             #_observation_date => $field->{observation_date}, # property not allowed
651              
652             iso8601duration => find_age(
653             {
654              
655             date => $field->{observation_date},
656             birth_day => $person->{birth_datetime}
657             }
658             )
659 158         783 };
660              
661             #$phenotypicFeature->{resolution} = undef;
662             #$phenotypicFeature->{severity} = undef;
663              
664             # NB: PROVISIONAL
665             # Longitudinal data are not allowed yet in BFF/PXF
666 158 50       444 if ( exists $self->{visit_occurrence} ) {
667             my $visit = map_omop_visit_occurrence(
668             {
669             person_id => $field->{person_id},
670             visit_occurrence_id => $field->{visit_occurrence_id},
671 158         1342 self => $self,
672             ohdsi_dic => $ohdsi_dic
673             }
674             );
675 158 100       446 $phenotypicFeature->{_visit} = $visit if defined $visit;
676             }
677              
678 158         210 push @{ $individual->{phenotypicFeatures} }, $phenotypicFeature;
  158         479  
679             }
680             }
681              
682             # ===
683             # sex
684             # ===
685              
686             # OHSDI CONCEPT.vocabulary_id = Gender (i.e., ad hoc)
687             my $sex = map2ohdsi(
688             {
689             ohdsi_dic => $ohdsi_dic,
690             concept_id => $person->{gender_concept_id},
691 68707         219202 self => $self
692             }
693             );
694              
695             # $sex = {id, label), we need to use 'label'
696             $individual->{sex} = map_ontology(
697             {
698             query => $sex->{label},
699 68707 50       345321 column => 'label',
700             ontology => 'ncit',
701             self => $self
702             }
703              
704             ) if $sex;
705              
706             # ==========
707             # treatments
708             # ==========
709              
710 68707         122528 $table = 'DRUG_EXPOSURE';
711              
712             # 1 days_supply
713             # 2 dose_unit_source_value
714             # 3 drug_concept_id
715             # 4 drug_exposure_end_date
716             # 5 drug_exposure_end_datetime
717             # 6 drug_exposure_id
718             # 7 drug_exposure_start_date
719             # 8 drug_exposure_start_datetime
720             # 9 drug_source_concept_id
721             # 10 drug_source_value
722             # 11 drug_type_concept_id
723             # 12 lot_number
724             # 13 person_id
725             # 14 provider_id
726             # 15 quantity
727             # 16 refills
728             # 17 route_concept_id
729             # 18 route_source_value
730             # 19 sig
731             # 20 stop_reason
732             # 21 verbatim_end_date
733             # 22 visit_detail_id
734             # 23 visit_occurrence_id
735              
736             # Example:
737              
738             # 'days_supply' => 35,
739             # 'dose_unit_source_value' => undef,
740             # 'drug_concept_id' => 19078461,
741             # 'drug_exposure_end_date' => '2014-11-19',
742             # 'drug_exposure_end_datetime' => '2014-11-19 00:00:00',
743             # 'drug_exposure_id' => 9656,
744             # 'drug_exposure_start_date' => '2014-10-15',
745             # 'drug_exposure_start_datetime' => '2014-10-15 00:00:00',
746             # 'drug_source_concept_id' => 19078461,
747             # 'drug_source_value' => 310965,
748             # 'drug_type_concept_id' => 38000177,
749             # 'lot_number' => 0,
750             # 'person_id' => 807,
751             # 'provider_id' => 0,
752             # 'quantity' => 0,
753             # 'refills' => 0,
754             # 'route_concept_id' => 0,
755             # 'route_source_value' => undef,
756             # 'sig' => undef,
757             # 'stop_reason' => undef,
758             # 'verbatim_end_date' => '2014-11-19',
759             # 'visit_detail_id' => 0,
760             # 'visit_occurrence_id' => 53547
761             # },
762              
763 68707 100       126941 if ( defined $participant->{$table} ) {
764              
765 67771         103077 $individual->{treatments} = [];
766              
767 67771         76123 for my $field ( @{ $participant->{$table} } ) {
  67771         151551  
768 68051         73712 my $treatment;
769              
770             $treatment->{ageAtOnset} = {
771             age => {
772              
773             # _birth_datetime => $person->{birth_datetime}, # property not allowed
774             # _drug_exposure_start_datetime => $field->{drug_exposure_start_date},
775             iso8601duration => find_age(
776             {
777             date => $field->{drug_exposure_start_date},
778             birth_day => $person->{birth_datetime}
779             }
780             )
781 68051         202891 }
782             };
783              
784             #$treatment->{cumulativeDose} = undef;
785 68051         159530 $treatment->{doseIntervals} = [];
786              
787             # #[{
788             # #_days_supply => $field->{days_supply}, # Property not allowed
789             # interval => {
790             # start => $field->{drug_exposure_start_date},
791             # end => $field->{drug_exposure_end_date}
792             # },
793             # quantity => {},
794             # scheduleFrequency => {}
795             #}];
796              
797             # _info (Autovivification)
798 68051         134888 $treatment->{_info}{$table}{OMOP_columns} = $field;
799              
800             $treatment->{routeOfAdministration} =
801 68051         138409 { id => "NCIT:NA0000", label => "Fake" };
802             $treatment->{treatmentCode} = map2ohdsi(
803             {
804             ohdsi_dic => $ohdsi_dic,
805             concept_id => $field->{drug_concept_id},
806             self => $self
807             }
808 68051 50       226550 ) if defined $field->{drug_concept_id};
809              
810             # NB: PROVISIONAL
811             # Longitudinal data are not allowed yet in BFF/PXF
812 68051 50       162007 if ( exists $self->{visit_occurrence} ) {
813             my $visit = map_omop_visit_occurrence(
814             {
815             person_id => $field->{person_id},
816             visit_occurrence_id => $field->{visit_occurrence_id},
817 68051         228558 self => $self,
818             ohdsi_dic => $ohdsi_dic
819             }
820             );
821 68051 100       161416 $treatment->{_visit} = $visit if defined $visit;
822             }
823              
824 68051         72637 push @{ $individual->{treatments} }, $treatment;
  68051         181809  
825             }
826             }
827              
828             ##################################
829             # END MAPPING TO BEACON V2 TERMS #
830             ##################################
831              
832 68707 50 66     189726 return ( $self->{stream} && avoid_duplicates($individual) )
833             ? undef
834             : $individual;
835             }
836              
837             sub avoid_duplicates {
838              
839 67707     67707 0 79114 my $hash = shift;
840              
841             # In stream mode, we need to eliminate duplicates
842             # Duplicates will only caontain keys id, info and sex
843             # Using the simplest possible comparison (with strings)
844 67707         80739 my $str_a = 'idinfosex';
845 67707         75539 my $str_b = join '', sort keys %{$hash};
  67707         342707  
846 67707 50       2324771 return $str_a eq $str_b ? 1 : 0;
847             }
848              
849             1;