File Coverage

lib/Pheno/Ranker.pm
Criterion Covered Total %
statement 211 222 95.0
branch 50 76 65.7
condition 24 36 66.6
subroutine 30 30 100.0
pod 0 2 0.0
total 315 366 86.0


line stmt bran cond sub pod time code
1             package Pheno::Ranker;
2              
3 5     5   852231 use strict;
  5         8  
  5         199  
4 5     5   23 use warnings;
  5         18  
  5         278  
5 5     5   2336 use autodie;
  5         56511  
  5         29  
6 5     5   32204 use feature qw(say);
  5         14  
  5         848  
7 5     5   3003 use Data::Dumper;
  5         38180  
  5         496  
8 5     5   44 use File::Basename qw(dirname);
  5         6  
  5         419  
9 5     5   27 use Cwd qw(abs_path);
  5         8  
  5         276  
10 5     5   1718 use File::Spec::Functions qw(catdir catfile);
  5         2881  
  5         371  
11 5     5   2629 use Term::ANSIColor qw(:constants);
  5         36912  
  5         4966  
12 5     5   3230 use Moo;
  5         43782  
  5         25  
13 5     5   14299 use Types::Standard qw(Str Int Num Enum ArrayRef HashRef Undef Bool);
  5         690050  
  5         72  
14 5     5   27072 use File::ShareDir::ProjectDistDir qw(dist_dir);
  5         166605  
  5         57  
15 5     5   2567 use List::Util qw(all);
  5         12  
  5         517  
16 5     5   3636 use Hash::Util qw(lock_hash);
  5         19579  
  5         62  
17 5     5   3701 use Pheno::Ranker::IO;
  5         26  
  5         646  
18 5     5   3648 use Pheno::Ranker::Compare;
  5         57  
  5         755  
19 5     5   53 use Pheno::Ranker::Metrics;
  5         13  
  5         512  
20 5     5   4178 use Pheno::Ranker::Graph;
  5         23  
  5         420  
21              
22 5     5   44 use Exporter 'import';
  5         20  
  5         1250  
23             our @EXPORT_OK = qw($VERSION write_json);
24              
25             # Personalize warn and die functions
26             $SIG{__WARN__} = sub { warn BOLD YELLOW "Warn: ", @_ };
27             $SIG{__DIE__} = sub { die BOLD RED "Error: ", @_ };
28              
29             # Global variables:
30             $Data::Dumper::Sortkeys = 1;
31             our $VERSION = '1.07';
32             our $share_dir = dist_dir('Pheno-Ranker');
33              
34             # Set development mode
35 5     5   43 use constant DEVEL_MODE => 0;
  5         10  
  5         26354  
36              
37             # Misc variables
38             my (
39             $config_sort_by, $config_similarity_metric_cohort,
40             $config_max_out, $config_max_number_vars,
41             $config_max_matrix_records_in_ram, @config_allowed_terms
42             );
43             my $default_config_file = catfile( $share_dir, 'conf', 'config.yaml' );
44              
45             ############################################
46             # Start declaring attributes for the class #
47             ############################################
48              
49             has 'config_file' => (
50             is => 'ro',
51             isa =>
52             sub { die "Config file '$_[0]' is not a valid file" unless -e $_[0] },
53             default => $default_config_file,
54             coerce => sub { $_[0] // $default_config_file },
55             trigger => sub {
56             my ( $self, $config_file ) = @_;
57             my $config = read_yaml($config_file);
58              
59             # Set basic configuration parameters
60             $self->_set_basic_config($config);
61              
62             # Validate and set exclusive configuration parameters
63             $self->_validate_and_set_exclusive_config( $config, $config_file );
64              
65             # Set additional configuration parameters on $self
66             $self->_set_additional_config( $config, $config_file );
67              
68             # Lock config data (keys+values)
69             lock_hash(%$config);
70             }
71             );
72              
73             # Private Method: _set_basic_config
74             sub _set_basic_config {
75 19     19   60 my ( $self, $config ) = @_;
76 19   100     109 $config_sort_by = $config->{sort_by} // 'hamming';
77             $config_similarity_metric_cohort = $config->{similarity_metric_cohort}
78 19   100     70 // 'hamming';
79 19   100     75 $config_max_out = $config->{max_out} // 50;
80 19   100     70 $config_max_number_vars = $config->{max_number_vars} // 10_000;
81             $config_max_matrix_records_in_ram = $config->{max_matrix_records_in_ram}
82 19   50     120 // 5_000;
83             }
84              
85             # Private Method: _validate_and_set_exclusive_config
86             sub _validate_and_set_exclusive_config {
87 19     19   46 my ( $self, $config, $config_file ) = @_;
88 19 50 33     223 unless ( exists $config->{allowed_terms}
      33        
89             && ArrayRef->check( $config->{allowed_terms} )
90 19         972 && @{ $config->{allowed_terms} } )
91             {
92 0         0 die "No provided or not an array ref at $config_file\n";
93             }
94 19         38 @config_allowed_terms = @{ $config->{allowed_terms} };
  19         208  
95             }
96              
97             # Private Method: _set_additional_config
98             sub _set_additional_config {
99 19     19   51 my ( $self, $config, $config_file ) = @_;
100              
101             # Setters
102 19   50     84 $self->{primary_key} = $config->{primary_key} // 'id';
103             $self->{exclude_variables_regex} = $config->{exclude_variables_regex}
104 19   100     83 // undef;
105             $self->{exclude_variables_regex_qr} =
106             defined $self->{exclude_variables_regex}
107 19 100       1026 ? qr/$self->{exclude_variables_regex}/
108             : undef;
109 19   100     85 $self->{array_terms} = $config->{array_terms} // ['foo'];
110 19   100     67 $self->{array_regex} = $config->{array_regex} // '^([^:]+):(\d+)';
111 19         462 $self->{array_regex_qr} = qr/$self->{array_regex}/;
112             $self->{array_terms_regex_str} =
113 19         137 '^(' . join( '|', map { "\Q$_\E" } @{ $self->{array_terms} } ) . '):';
  169         460  
  19         52  
114 19         399 $self->{array_terms_regex_qr} = qr/$self->{array_terms_regex_str}/;
115 19         63 $self->{format} = $config->{format};
116             $self->{seed} =
117             ( defined $config->{seed} && Int->check( $config->{seed} ) )
118             ? $config->{seed}
119 19 100 66     133 : 123456789;
120              
121 19 100       253 if ( $self->{array_terms}[0] ne 'foo' ) {
122 18 50 33     157 unless ( exists $config->{id_correspondence}
123             && HashRef->check( $config->{id_correspondence} ) )
124             {
125 0         0 die
126             "No provided or not a hash ref at $config_file\n";
127             }
128 18         376 $self->{id_correspondence} = $config->{id_correspondence};
129 18 100 66     92 if ( exists $config->{format} && Str->check( $config->{format} ) ) {
130             die
131             "<$config->{format}> does not match any key from \n"
132 3 50       41 unless exists $config->{id_correspondence}{ $config->{format} };
133             }
134             }
135             }
136              
137             has sort_by => (
138             default => $config_sort_by,
139             is => 'ro',
140             coerce => sub { $_[0] // $config_sort_by },
141             lazy => 1,
142             isa => Enum [qw(hamming jaccard)]
143             );
144              
145             has similarity_metric_cohort => (
146             default => $config_similarity_metric_cohort,
147             is => 'ro',
148             coerce => sub { $_[0] // $config_similarity_metric_cohort },
149             lazy => 1,
150             isa => Enum [qw(hamming jaccard)]
151             );
152              
153             has max_out => (
154             default => $config_max_out,
155             is => 'ro',
156             coerce => sub { $_[0] // $config_max_out },
157             lazy => 1,
158             isa => Int
159             );
160              
161             has max_number_vars => (
162             default => $config_max_number_vars,
163             is => 'ro',
164             coerce => sub { $_[0] // $config_max_number_vars },
165             lazy => 1,
166             isa => Int
167             );
168              
169             has max_matrix_records_in_ram => (
170             default => $config_max_matrix_records_in_ram,
171             is => 'ro',
172             coerce => sub { $_[0] // $config_max_matrix_records_in_ram },
173             lazy => 1,
174             isa => Int
175             );
176              
177             has hpo_file => (
178             default => catfile( $share_dir, 'db', 'hp.json' ),
179             coerce => sub { $_[0] // catfile( $share_dir, 'db', 'hp.json' ) },
180             is => 'ro',
181             isa => sub { die "Error <$_[0]> is not a valid file" unless -e $_[0] },
182             );
183              
184             has poi_out_dir => (
185             default => catdir('./'),
186             coerce => sub { $_[0] // catdir('./') },
187             is => 'ro',
188             isa => sub { die "<$_[0]> dir does not exist" unless -d $_[0] },
189             );
190              
191             has [qw/include_terms exclude_terms/] => (
192             is => 'ro',
193             lazy => 1,
194             isa => sub {
195             my $value = shift;
196             die "<--include_terms> and <--exclude_terms> must be an array ref\n"
197             unless ref $value eq 'ARRAY';
198             foreach my $term (@$value) {
199             die
200             "Invalid term '$term' in <--include_terms> or <--exclude_terms>. Allowed values are: "
201             . join( ', ', @config_allowed_terms ) . "\n"
202             unless grep { $_ eq $term } @config_allowed_terms;
203             }
204             },
205             default => sub { [] },
206             );
207              
208             has cli => (
209             is => 'ro',
210             isa => Bool,
211             default => 0,
212             coerce => sub { $_[0] // 0 },
213             );
214              
215             # Miscellaneous attributes
216             has [
217             qw/target_file weights_file out_file include_hpo_ascendants
218             retain_excluded_phenotypicFeatures align align_basename export export_basename
219             log verbose age cytoscape_json graph_stats/
220             ] => ( is => 'ro' );
221              
222             has [qw/append_prefixes reference_files patients_of_interest/] =>
223             ( default => sub { [] }, is => 'ro' );
224              
225             has [qw/glob_hash_file ref_hash_file ref_binary_hash_file coverage_stats_file/]
226             => ( is => 'ro' );
227              
228             ##########################################
229             # End declaring attributes for the class #
230             ##########################################
231              
232             sub BUILD {
233              
234             # BUILD: is an instance method that is called after the object has been constructed but before it is returned to the caller.
235             # BUILDARGS is a class method that is responsible for processing the arguments passed to the constructor (new) and returning a hash reference of attributes that will be used to initialize the object.
236              
237 19     19 0 610 my $self = shift;
238              
239             # Miscellaneous checks
240 19 100       29 if ( @{ $self->{append_prefixes} } ) {
  19         65  
241             die "<--append_prefixes> requires at least 2 cohort files!\n"
242 1 50       1 unless @{ $self->{reference_files} } > 1;
  1         4  
243             die "The number of items in <--r> and <--append-prefixes> must match!\n"
244 1 50       2 unless @{ $self->{reference_files} } == @{ $self->{append_prefixes} };
  1         2  
  1         3  
245             }
246 19 50       29 if ( @{ $self->{patients_of_interest} } ) {
  19         318  
247             die "<--patients-of-interest> must be used with <--r>\n"
248 0 0       0 unless @{ $self->{reference_files} };
  0         0  
249             }
250             }
251              
252             # ============================================================
253             # run method
254             # ============================================================
255             sub run {
256 19     19 0 400 my $self = shift;
257              
258             # -----------------------------------------------------
259             # Retrieve configuration parameters from the object
260             # -----------------------------------------------------
261 19         42 my $reference_files = $self->{reference_files};
262 19         44 my $target_file = $self->{target_file};
263 19         33 my $weights_file = $self->{weights_file};
264 19         78 my $export = $self->{export};
265 19         39 my $export_basename = $self->{export_basename};
266 19         32 my $include_hpo_ascendants = $self->{include_hpo_ascendants};
267 19         44 my $hpo_file = $self->{hpo_file};
268 19         41 my $align = $self->{align};
269 19         44 my $align_basename = $self->{align_basename};
270 19         40 my $out_file = $self->{out_file};
271 19         32 my $cytoscape_json = $self->{cytoscape_json};
272 19         31 my $graph_stats = $self->{graph_stats};
273 19         96 my $append_prefixes = $self->{append_prefixes};
274 19         38 my $primary_key = $self->{primary_key};
275 19         37 my $poi = $self->{patients_of_interest};
276 19         37 my $poi_out_dir = $self->{poi_out_dir};
277 19         30 my $cli = $self->{cli};
278 19         37 my $similarity_metric_cohort = $self->{similarity_metric_cohort};
279 19         36 my $weight = undef;
280              
281             # -----------------------------------------------------
282             # Check directories for --align and --export options
283             # -----------------------------------------------------
284 19 100       702 my $align_dir = defined $align ? dirname($align) : '.';
285 19 50       339 die "Directory <$align_dir> does not exist (used with --align)\n"
286             unless -d $align_dir;
287 19 50       71 my $export_dir = defined $export ? dirname($export) : '.';
288 19 50       155 die "Directory <$export_dir> does not exist (used with --export)\n"
289             unless -d $export_dir;
290              
291             # -----------------------------------------------------
292             # Check for precomputed data (glob_hash, ref_hash, ref_binary_hash, coverage_stats)
293             # -----------------------------------------------------
294             my $has_precomputed =
295             defined $self->{glob_hash_file}
296             && defined $self->{ref_hash_file}
297             && defined $self->{ref_binary_hash_file}
298 19   33     96 && defined $self->{coverage_stats_file};
299              
300             my (
301 19         49 $glob_hash, $ref_hash, $ref_binary_hash,
302             $coverage_stats, $hash2serialize
303             );
304              
305 19 100       71 if ($has_precomputed) {
306              
307 1 50       5 say "Using precomputed data" if $self->{verbose};
308              
309             # Use precomputed data provided via Moo attributes
310 1         6 $glob_hash = read_json( $self->{glob_hash_file} );
311 1         6 $ref_hash = read_json( $self->{ref_hash_file} );
312 1         7 $ref_binary_hash = read_json( $self->{ref_binary_hash_file} );
313 1         6 $coverage_stats = read_json( $self->{coverage_stats_file} );
314              
315             # Set format from *.coverage_stats.json
316 1         8 $self->_add_attribute( 'format', $coverage_stats->{format} );
317              
318 1         7 $hash2serialize = {
319             glob_hash => $glob_hash,
320             ref_hash => $ref_hash,
321             ref_binary_hash => $ref_binary_hash,
322             };
323             }
324             else {
325             # -----------------------------------------------------
326             # Part A: Load reference cohort data
327             # -----------------------------------------------------
328 18         69 my $ref_data =
329             $self->_load_reference_cohort_data( $reference_files, $primary_key,
330             $append_prefixes );
331              
332             #-------------------------------
333             # Write json for $poi if --poi |
334             #-------------------------------
335             # *** IMPORTANT ***
336             # It will exit when done (dry-run)
337 18 50       51 if (@$poi) {
338             write_poi(
339             {
340             ref_data => $ref_data,
341             poi => $poi,
342             poi_out_dir => $poi_out_dir,
343             primary_key => $primary_key,
344             verbose => $self->{verbose}
345             }
346 0         0 );
347              
348             # premature return
349 0         0 return 1;
350             }
351              
352             # -----------------------------------------------------
353             # Load weights file and HPO data if needed
354             # -----------------------------------------------------
355             # We assing weights if <--w>
356             # NB: The user can exclude variables by using variable: 0
357 18         77 $weight = validate_json($weights_file);
358              
359             # Now we load $hpo_nodes, $hpo_edges if --include_hpo_ascendants
360             # NB: we load them within $self to minimize the #args
361              
362 16 50       94 if ($include_hpo_ascendants) {
363 0         0 my ( $nodes, $edges ) = parse_hpo_json( read_json($hpo_file) );
364 0         0 $self->{nodes} = $nodes;
365 0         0 $self->{edges} = $edges;
366             }
367              
368             # -----------------------------------------------------
369             # Part B: Compute cohort metrics
370             # -----------------------------------------------------
371 16         76 my ( $coverage_stats, $glob_hash_computed, $ref_hash_computed,
372             $ref_binary_hash_computed, $hash2serialize_computed )
373             = $self->_compute_cohort_metrics( $ref_data, $weight, $primary_key,
374             $target_file );
375              
376 15         27 $glob_hash = $glob_hash_computed;
377 15         27 $ref_hash = $ref_hash_computed;
378 15         26 $ref_binary_hash = $ref_binary_hash_computed;
379 15         35400 $hash2serialize = $hash2serialize_computed;
380             }
381              
382             # -----------------------------------------------------
383             # If no target file is provided, perform cohort comparison
384             # -----------------------------------------------------
385 16 100       164 cohort_comparison( $ref_binary_hash, $self ) unless $target_file;
386              
387             # Create and write Cytoscape JSON if requested
388 16         119 my $graph = $self->_perform_graph_calculations( $out_file, $cytoscape_json,
389             $graph_stats, $similarity_metric_cohort );
390              
391             # -----------------------------------------------------
392             # Part C: Process patient data (if target_file is provided)
393             # -----------------------------------------------------
394 16 100       67 if ($target_file) {
395             $self->_process_patient_data(
396             {
397             target_file => $target_file,
398             primary_key => $primary_key,
399             weight => $weight,
400             glob_hash => $glob_hash,
401             ref_hash => $ref_hash,
402             ref_binary_hash => $ref_binary_hash,
403             align => $align,
404             align_basename => $align_basename,
405             out_file => $out_file,
406             cli => $cli,
407             verbose => $self->{verbose},
408             },
409 2         64 \$hash2serialize
410             );
411             }
412              
413             # -----------------------------------------------------
414             # Export JSON if requested
415             # -----------------------------------------------------
416 16 50       87 if ( defined $export ) {
417 0 0       0 serialize_hashes(
418             {
419             data => $hash2serialize,
420             export_basename => $export ? $export : $export_basename
421             }
422             );
423             }
424              
425 16         6665 return 1;
426             }
427              
428             # ============================================================
429             # Private method: _load_reference_cohort_data
430             # ------------------------------------------------------------
431             # Loads each reference cohort file, validates the primary_key,
432             # and then appends prefixes if needed.
433             # ============================================================
434             sub _load_reference_cohort_data {
435 18     18   47 my ( $self, $reference_files, $primary_key, $append_prefixes ) = @_;
436              
437             # *** IMPORTANT ***
438             # $ref_data is an array array where each element is the content of the file (e.g, [] or {})
439              
440 18         37 my $ref_data = [];
441 18         28 for my $cohort_file ( @{$reference_files} ) {
  18         63  
442 16 50       218 die "<$cohort_file> does not exist\n" unless -f $cohort_file;
443 16         134 my $json_data = io_yaml_or_json(
444             {
445             filepath => $cohort_file,
446             mode => 'read'
447             }
448             );
449              
450             # Check for existence of primary_key otherwise die
451             # Expected cases:
452             # - A) BFF/PXF (default config) exists primary_key('id')
453             # - B) JSON (default config) exists primary_key('id') - i.e., OpenEHR
454             # - C) JSON (external config) exists primary_key
455              
456 16         82 my $msg =
457             "Sorry, <$cohort_file> does not contain primary_key <$primary_key>. Are you using the right configuration file?\n";
458 16 100       73 if ( ref $json_data eq ref [] ) {
459 15 50       69 die $msg unless exists $json_data->[0]->{$primary_key};
460             }
461             else {
462 1 50       4 die $msg unless exists $json_data->{$primary_key};
463             }
464 16         61 push @$ref_data, $json_data;
465             }
466              
467             # In we join --cohorts into one but we rename the values of primary_key
468             # NB: Re-using $ref_data to save memory
469              
470 18         241 $ref_data = append_and_rename_primary_key(
471             {
472             ref_data => $ref_data,
473             append_prefixes => $append_prefixes,
474             primary_key => $primary_key
475             }
476             );
477 18         68 return $ref_data;
478             }
479              
480             # ============================================================
481             # Private method: _compute_cohort_metrics
482             # ------------------------------------------------------------
483             # Computes cohort coverage statistics, restructures the data
484             # (e.g. PXF interpretations), and then creates the global and
485             # per-individual hashes along with their one-hot encoded version.
486             # ============================================================
487             sub _compute_cohort_metrics {
488 16     16   51 my ( $self, $ref_data, $weight, $primary_key, $target_file ) = @_;
489 16         43 my $export = $self->{export};
490              
491             # We have to check if we have BFF|PXF or others (unless defined at config)
492             $self->_add_attribute( 'format', check_format($ref_data) )
493 16 100       116 unless defined $self->{format};
494              
495 16         69 my $coverage_stats = coverage_stats( $ref_data, $self->{format} );
496             die
497 1         23 "--include-terms <@{$self->{include_terms}}> does not exist in the cohort(s)\n"
498             unless check_existence_of_include_terms( $coverage_stats,
499 16 100       79 $self->{include_terms} );
500              
501             # Restructure PXF
502 15         67 restructure_pxf_interpretations( $ref_data, $self );
503              
504             # First we create:
505             # - $glob_hash => hash with all the COHORT keys possible
506             # - $ref_hash => BIG hash with all individiduals' keys "flattened"
507              
508 15         84 my ( $glob_hash, $ref_hash ) =
509             create_glob_and_ref_hashes( $ref_data, $weight, $self );
510              
511             # Limit the number of variables if > $self-{max_number_vars}
512             # *** IMPORTANT ***
513             # Change only performed in $glob_hash
514 15 50       103 if ( keys %$glob_hash > $self->{max_number_vars} ) {
515 0         0 $glob_hash = randomize_variables( $glob_hash, $self );
516             }
517              
518             # Second we peform one-hot encoding for each individual
519 15         87 my $ref_binary_hash =
520             create_binary_digit_string( $export, $weight, $glob_hash, $ref_hash );
521              
522             # Hashes to be serialized to JSON if <--export>
523 15         127 my $hash2serialize = {
524             glob_hash => $glob_hash,
525             ref_hash => $ref_hash,
526             ref_binary_hash => $ref_binary_hash,
527             coverage_stats => $coverage_stats
528             };
529             return (
530 15         91 $coverage_stats, $glob_hash, $ref_hash,
531             $ref_binary_hash, $hash2serialize
532             );
533             }
534              
535             # ============================================================
536             # Private method: _process_patient_data
537             # ------------------------------------------------------------
538             # Loads patient data from the target file, validates it,
539             # restructures interpretations, and then performs the patient
540             # to cohort comparison and ranking.
541             # ============================================================
542             sub _process_patient_data {
543 2     2   8 my ( $self, $params, $hash2serialize_ref ) = @_;
544 2         6 my $target_file = $params->{target_file};
545 2         6 my $primary_key = $params->{primary_key};
546 2         32 my $weight = $params->{weight};
547 2         6 my $glob_hash = $params->{glob_hash};
548 2         5 my $ref_hash = $params->{ref_hash};
549 2         10 my $ref_binary_hash = $params->{ref_binary_hash};
550 2         5 my $align = $params->{align};
551 2         5 my $align_basename = $params->{align_basename};
552 2         5 my $out_file = $params->{out_file};
553 2         4 my $cli = $params->{cli};
554 2         4 my $verbose = $params->{verbose};
555 2         6 my $export = $self->{export};
556              
557 2         27 my $tar_data = array2object(
558             io_yaml_or_json( { filepath => $target_file, mode => 'read' } ) );
559              
560             # The target file has to have $_->{$primary_key} otherwise die
561              
562             die
563             "Sorry, <$target_file> does not contain primary_key <$primary_key>. Are you using the right config file?\n"
564 2 50       12 unless exists $tar_data->{$primary_key};
565 2         14 restructure_pxf_interpretations( $tar_data, $self );
566              
567             # We store {primary_key} as a variable as it might be deleted from $tar_data (--exclude-terms id)
568              
569 2         23 my $tar_data_id = $tar_data->{$primary_key};
570 2         26 my $tar_hash = {
571             $tar_data_id => remap_hash(
572             {
573             hash => $tar_data,
574             weight => $weight,
575             self => $self
576             }
577             )
578             };
579              
580             # *** IMPORTANT ***
581             # The target binary is created from matches to $glob_hash
582             # Thus, it does not include variables ONLY present in TARGET
583              
584 2         243 my $tar_binary_hash =
585             create_binary_digit_string( $export, $weight, $glob_hash, $tar_hash );
586             my (
587 2         26 $results_rank, $results_align, $alignment_ascii,
588             $alignment_dataframe, $alignment_csv
589             )
590             = compare_and_rank(
591             {
592             glob_hash => $glob_hash,
593             ref_hash => $ref_hash,
594             tar_hash => $tar_hash,
595             ref_binary_hash => $ref_binary_hash,
596             tar_binary_hash => $tar_binary_hash,
597             weight => $weight,
598             self => $self
599             }
600             );
601 2 50       19 say join "\n", @$results_rank if $cli;
602 2         24 write_array2txt( { filepath => $out_file, data => $results_rank } );
603              
604 2 50       12 if ( defined $align ) {
605 2 50       23 write_alignment(
606             {
607             align => $align ? $align : $align_basename,
608             ascii => $alignment_ascii,
609             dataframe => $alignment_dataframe,
610             csv => $alignment_csv
611             }
612             );
613             }
614 2         19 $$hash2serialize_ref->{tar_hash} = $tar_hash;
615 2         13 $$hash2serialize_ref->{tar_binary_hash} = $tar_binary_hash;
616 2 50       12 $$hash2serialize_ref->{alignment_hash} = $results_align if defined $align;
617 2         3087 return 1;
618             }
619              
620             sub _perform_graph_calculations {
621 16     16   74 my ( $self, $out_file, $cytoscape_json, $graph_stats,
622             $similarity_metric_cohort )
623             = @_;
624              
625 16         53 my $graph;
626 16 100       50 if ($cytoscape_json) {
627             $graph = matrix2graph(
628             {
629             matrix => $out_file,
630             json => $cytoscape_json,
631             graph_stats => 1,
632             verbose => $self->{verbose},
633             }
634 1         15 );
635             }
636              
637 16 100       59 if ( defined $graph_stats ) {
638             cytoscape2graph(
639             {
640             graph => $graph,
641             output => $graph_stats,
642             metric => $similarity_metric_cohort,
643             verbose => $self->{verbose},
644             }
645 1         13 );
646             }
647              
648 16         60 return $graph;
649             }
650              
651             sub _add_attribute {
652 14     14   41 my ( $self, $name, $value ) = @_;
653 14         47 $self->{$name} = $value;
654 14         31 return 1;
655             }
656              
657             1;
658              
659             =pod
660              
661             =head1 NAME
662              
663             Convert::Pheno - A module that performs semantic similarity in PXF/BFF data structures and beyond (JSON|YAML)
664            
665             =head1 SYNOPSIS
666              
667             use Pheno::Ranker;
668              
669             # Create object
670             my $ranker = Pheno::Ranker->new(
671             {
672             reference_files => ['individuals.json'],
673             out_file => 'matrix.txt'
674             }
675             );
676              
677             # Run it (output are text files)
678             $ranker->run;
679              
680             =head1 DESCRIPTION
681              
682             We recommend using the included L.
683              
684             For a better description, please read the following documentation:
685              
686             =over
687              
688             =item General:
689              
690             L
691              
692             =item Command-Line Interface:
693              
694             L
695              
696             =back
697              
698             =head1 CITATION
699              
700             The author requests that any published work that utilizes `Pheno-Ranker` includes a cite to the following reference:
701              
702             Leist, I.C. et al., (2024). Pheno-Ranker: a toolkit for comparison of phenotypic data stored in GA4GH standards and beyond. _BMC Bioinformatics_. DOI: 10.1186/s12859-024-05993-2
703              
704             =head1 AUTHOR
705              
706             Written by Manuel Rueda, PhD. Info about CNAG can be found at L.
707              
708             =head1 METHODS
709              
710             There is only method named C. See above the syntax.
711              
712             For more information check the documentation:
713              
714             L
715              
716             =head1 COPYRIGHT
717              
718             This PERL file is copyrighted. See the LICENSE file included in this distribution.
719              
720             =cut