3 start include statements
5 use ext
::Math
::MatrixReal
;
10 # }}} include statements
16 if ( defined $this -> {'tablename'} ) {
17 $this -> add_data
( 'init_data' => {'filename' => $this -> {'tablename'},
18 'idcolumn' => $this -> {'tableidcolumn'},
19 'debug' => $this -> {'debug'}} );
22 $this -> _read_simulation
;
24 if( $this -> estimation_step_run
() ) {
25 $this -> _read_iteration_path
;
26 $this -> _read_term
() if ($this -> parsed_successfully
() and not
27 $this -> finished_parsing
());
30 if( $this -> estimation_step_initiated
() ) {
31 $this -> _read_ofv
() if ($this -> parsed_successfully
() and not
32 $this -> finished_parsing
());
33 $this -> _read_thomsi
() if ($this -> parsed_successfully
() and not
34 $this -> finished_parsing
());
35 if ($this -> covariance_step_run
() ) {
36 $this -> _read_sethomsi
() if ($this -> parsed_successfully
() and not
37 $this -> finished_parsing
());
38 if ($this -> parsed_successfully
()) {
39 $this -> _compute_cvsetheta
();
40 $this -> _compute_cvseomega
();
41 $this -> _compute_cvsesigma
();
44 if ($this -> parsed_successfully
() and defined $this -> thetas
() ) {
45 $this -> _set_thetanames
();
47 if ($this -> parsed_successfully
() and defined $this -> omegas
() ) {
48 $this -> _compute_comegas
();
49 $this -> _set_omeganames
();
51 if ($this -> parsed_successfully
() and defined $this -> sigmas
() ) {
52 $this -> _compute_csigmas
();
53 $this -> _set_sigmanames
();
57 if ($this -> covariance_step_run
()) {
58 $this -> _read_covmatrix
() if ($this -> parsed_successfully
() and not
59 $this -> finished_parsing
());
60 $this -> _read_eigen
() if ($this -> parsed_successfully
() and not
61 $this -> finished_parsing
());
64 if( $this -> nonparametric_step_run
() ) {
65 $this -> _read_npomegas
() if ($this -> parsed_successfully
() and not
66 $this -> finished_parsing
());
69 delete $this -> {'lstfile'};
78 $self -> parsed_successfully
( 0 );
79 $self -> parsing_error_message
( $message );
83 # {{{ register_in_database
85 start register_in_database
86 if ( $PsN::config
-> {'_'} -> {'use_database'} ) {
87 my $dbh = DBI
-> connect("DBI:mysql:host=".$PsN::config
-> {'_'} -> {'database_server'}.
88 ";databse=".$PsN::config
-> {'_'} -> {'project'},
89 $PsN::config
-> {'_'} -> {'user'},
90 $PsN::config
-> {'_'} -> {'password'},
94 if ( defined $self->{'minimization_message'} ) {
95 $term_str = join("\n",@
{$self->{'minimization_message'}});
97 my @mod_str = ('','');
98 if ( defined $model_id ) {
99 @mod_str = ('model_id,',"$model_id,");
101 $sth = $dbh -> prepare
("INSERT INTO ".$PsN::config
-> {'_'} -> {'project'}.
103 "(problem_id,output_id,".
106 "covariance_step_successful,".
107 "covariance_step_warnings,".
109 "final_zero_gradients,".
113 "s_matrix_singular,".
114 "significant_digits,".
116 "minimization_successful,".
117 "minimization_message,".
119 "VALUES ( '$problem_id' ,".
122 "'$self->{'condition_number'}' ,".
123 "'$self->{'covariance_step_successful'}' ,".
124 "'$self->{'covariance_step_warnings'}' ,".
125 "'$self->{'eval'}' ,".
126 "'$self->{'final_zero_gradients'}' ,".
127 "'$self->{'hessian_reset'}' ,".
128 "'$self->{'ofv'}' ,".
129 "'$self->{'rounding_errors'}' ,".
130 "'$self->{'s_matrix_singular'}' ,".
131 "'$self->{'significant_digits'}' ,".
132 "'$self->{'simulation'}' ,".
133 "'$self->{'minimization_successful'}' ,".
135 "'$self->{'zero_gradients'}' )");
137 $self -> {'subproblem_id'} = $sth->{'mysql_insertid'};
138 $self -> {'problem_id'} = $problem_id;
139 $self -> {'output_id'} = $output_id;
140 $self -> {'model_id'} = $model_id;
141 foreach my $param ( 'theta', 'omega', 'sigma' ) {
143 foreach my $par_str ( @
{$self -> {$param.'s'}} ) {
144 $sth = $dbh -> prepare
("INSERT INTO ".$PsN::config
-> {'_'} -> {'project'}.
146 "(subproblem_id,problem_id,output_id,".
148 "type,value, number, label) ".
149 "VALUES ( '$self->{'subproblem_id'}' ,".
150 "'$self->{'problem_id'}' ,".
151 "'$self->{'output_id'}' ,".
153 "'$param','$par_str', '$i', 'test_label')");
155 push( @
{$self -> {'estimate_ids'}}, $sth->{'mysql_insertid'} );
163 # if ( $PsN::config -> {'_'} -> {'use_database'} ) {
164 # my $dbh = DBI -> connect("DBI:mysql:host=".$PsN::config -> {'_'} -> {'database_server'}.
165 # ";databse=".$PsN::config -> {'_'} -> {'project'},
166 # $PsN::config -> {'_'} -> {'user'},
167 # $PsN::config -> {'_'} -> {'password'},
168 # {'RaiseError' => 1});
169 # my $sth = $dbh -> prepare( "UPDATE ".$PsN::config -> {'_'} -> {'project'}.
171 # "SET condition_number='".
172 # $self -> {'condition_number'}."'".
173 # "WHERE model_id='".$self -> {'model_id'}."'" );
174 # $sth -> execute or debug -> die( message => $sth->errstr ) ;
176 # $dbh -> disconnect;
178 end register_in_database
180 # }}} register_in_database
182 # {{{ _compute_comegas_or_csigmas
184 start _compute_comegas_or_csigmas
186 # This method transforms omegas or sigmas.
188 # First we check if we have omegas or sigmas.
189 if ( defined $self -> {'raw_' . $omega_or_sigma . 's'} ) {
190 my @raw_omegas_or_sigmas = @
{$self -> {'raw_' . $omega_or_sigma . 's'}};
191 # If the omega or sigma matrix has no off-diagonal elements, the
192 # transformation is quite straightforward.
193 if( $self -> { $omega_or_sigma . '_block_structure_type'} eq 'DIAGONAL' ){
195 # All diagonal omegas or sigmas will be in
196 # @raw_omegas_or_sigmas, so we loop over it and take the square
197 # root of non-negative, non-zero numbers (those become
200 for( my $i = 0; $i <= $#raw_omegas_or_sigmas; $i+=$row_size ){
201 my $omega_or_sigma_value = undef;
202 if( $raw_omegas_or_sigmas[$i] >= 0 ) {
203 $omega_or_sigma_value = sqrt( $raw_omegas_or_sigmas[$i] );
205 ui
-> print( category
=> 'all',
206 message
=> "Warning: cannot take the square root of ".
207 "$omega_or_sigma with value ".$raw_omegas_or_sigmas[$i] );
209 push( @
{$self -> {'c' . $omega_or_sigma .'s'}}, $omega_or_sigma_value );
213 } elsif( $self -> {$omega_or_sigma . '_block_structure_type'} eq 'BLOCK' ) {
215 # If the omega or sigma matrix has block form, the transformation
216 # becomes a bit more complex. The transformation for diagonal
217 # elements is the same. But for off-diagonals it takes more into
220 # $current_row_size is the number of omegas or sigmas in the row
221 # in the matrix that we are currently transforming.
222 my $current_row_size = 1;
224 # $diagonal_index is the index in @raw_omegas_or_sigmas where the current
225 # on-diagonal omega or sigma we are transforming.
226 my $diagonal_index = 0;
228 # $y is the y-coordinate of the element in the matrix we
232 # First get all block sets sorted.
233 my @keys = sort {$a <=> $b} keys( %{$self -> { $omega_or_sigma . '_block_sets'}} );
235 foreach my $key ( @keys ) {
237 # If this is a block set $block_dimension will be > 1
238 # otherwise it will be 1.
239 my $block_dimension = $self -> { $omega_or_sigma . '_block_sets'}{$key}{'dimension'};
240 my $block_size = $self -> { $omega_or_sigma . '_block_sets'}{$key}{'size'};
242 # print "BS: $block_size\n";
243 # print "BD: $block_dimension\n";
245 # loop over the repeated blocks
246 for( my $i = 1; $i <= $block_size; $i++ ) {
247 # loop over the size of the block (i.e. the X in block(X))
248 for( my $j = 1; $j <= $block_dimension; $j++ ) {
251 # The equation y*(y+1)/2 is a geometric sum that gives the
252 # index of the diagonal element on row y in the compacted
253 # matrixarray @raw_omegas_or_sigmas. -1 to get array
255 my $y_y_idx = ($y*($y+1)/2)-1;
257 my $start_x = ($y - $j + 1);
258 for( my $x = $start_x; $x <= $y; $x++ ) {
259 # print "X: $x, Y: $y\n";
260 my $omega_or_sigma_value;
262 # This is the first of the repeated blocks, collect
263 # the values (otherwise, just leave
264 # omega_or_sigma_value undefined)
267 # If we are on the diagonal, just take the square root
268 # of the diagonal element.
269 $omega_or_sigma_value = $raw_omegas_or_sigmas[ $y_y_idx ];
270 $omega_or_sigma_value = sqrt( $omega_or_sigma_value );
271 # print "y_y_idx: $y_y_idx\n";
274 # If we are off the diagonal, we need to find two
275 # on-diagonal omegas, one on the same column and one on
278 my $x_x_idx = ($x*($x+1)/2)-1; # See explanation for $y_y_idx above
280 # Off diagonal index: $y_y_idx for the row before plus $x
281 my $x_y_idx = (($y-1)*$y/2+$x)-1;
283 $omega_or_sigma_value = $raw_omegas_or_sigmas[$x_y_idx];
284 my $denominator = $raw_omegas_or_sigmas[ $x_x_idx ]
285 * $raw_omegas_or_sigmas[ $y_y_idx ];
286 if( $denominator <= 0 ){ # To avoiding division by zero
287 $omega_or_sigma_value = undef;
288 } elsif( $omega_or_sigma_value >= sqrt($denominator) ) {
289 # This rounding handles cases when the offdiagonals
290 # are greater or equal to one.
291 $omega_or_sigma_value = $omega_or_sigma_value/( int( 10000 * sqrt($denominator) )/10000 );
293 $omega_or_sigma_value = $omega_or_sigma_value/sqrt($denominator);
297 push( @
{$self -> {'c' . $omega_or_sigma . 's'}}, $omega_or_sigma_value );
303 # my $loop_limit = $block_dimension > $block_size ? $block_dimension : $block_size;
304 # print "loop limit: $loop_limit\n";
305 # for( my $i = 0; $i < $loop_limit; $i ++ ){
306 # # x_idx is the x-coordinate of the omega or sigma we are
309 # my $x_idx = $y_idx - $i;
310 # # current row size is equal to the y coordinate
311 # # my $x_idx = $current_row_size - $i;
313 # # The innner_loop_limit must be 1 when we have SAME blocks,
314 # # which can be determined from the block_size variable.
315 # my $inner_loop_limit = $block_size > 1 ? 0 : $i;
316 # print "inner loop limit: $inner_loop_limit\n";
317 # # The inner loop is over the row elements in the block
318 # # set. (1 when we have SAME blocks)
319 # for( my $j = 0; $j <= $inner_loop_limit; $j++ ){
321 # # $omega_or_sigma will hold the transformed value.
322 # my $omega_or_sigma_value;
324 # print "X: $x_idx, Y: $y_idx\n";
325 # if( $x_idx == $y_idx ) {
327 # # If we are on the diagonal, just take the square root
328 # # of the diagonal element.
329 # $omega_or_sigma_value = $raw_omegas_or_sigmas[ $diagonal_index ];
330 # $omega_or_sigma_value = sqrt( $omega_or_sigma_value );
333 # # If we are off the diagonal, we need to find two
334 # # on-diagonal omegas, one on the same column and one on
337 # # The equation y*(y+1)/2 is a geometric sum that gives
338 # # the index of the diagonal element on row y in the
339 # # compacted matrixarray @raw_omegas_or_sigmas. The equation
340 # # x*(x+1)/2 gives the diagonal element on column x in
343 # # We find the omega by finding the index of the diagonal
344 # # element on row y and subtracting the difference
345 # # between the number of elements on the row ($i) and the
346 # # number of elements we have transformed ($j).
348 # $omega_or_sigma_value = $raw_omegas_or_sigmas[(($y_idx*($y_idx+1))/2)-1 - ($i - $j)];
349 # my $denominator = $raw_omegas_or_sigmas[ (($x_idx*($x_idx+1))/2)-1 ]
351 # $raw_omegas_or_sigmas[ (($y_idx*($y_idx+1))/2)-1 ];
352 # if( $denominator <= 0 ){ # To avoiding division by zero
353 # $omega_or_sigma_value = undef;
354 # } elsif( $omega_or_sigma_value >= sqrt($denominator) ) {
355 # # This rounding handles cases when the offdiagonals
356 # # are greater or equal to one.
357 # $omega_or_sigma_value = $omega_or_sigma_value/( int( 10000 * sqrt($denominator) )/10000 )
359 # $omega_or_sigma_value = $omega_or_sigma_value/sqrt($denominator);
362 # push( @{$self -> {'c' . $omega_or_sigma . 's'}}, $omega_or_sigma_value );
364 # # Move the x-coordinate forwards.
368 # # Move the y-coordinate forwards.
370 # # Calculate the new row size.
371 # # $current_row_size ++;
372 # # Skip one row and we get the index of the next diagonal.
374 # $diagonal_index += $y_idx;
375 # # $diagonal_index += $current_row_size;
379 'debug' -> warn( level
=> 1,
380 message
=> $omega_or_sigma . ' matrix has unknown form.' );
384 end _compute_comegas_or_csigmas
386 # }}} _compute_comegas_or_sigmas
388 # {{{ _compute_comegas
389 start _compute_comegas
391 $self -> _compute_comegas_or_csigmas
( omega_or_sigma
=> 'omega' );
395 # This is the old algoritm for transforming omegas. It can't handle
396 # of-diagonals omegas that are zero, if that should ever happen.
400 # my @computed_omegas;
404 # @raw_omegas = @{$self -> {'raw_omegas'}};
405 # @computed_omegas = ();
407 # if( $self -> {'omega_structure_type'} eq 'DIAGONAL' ){
408 # @diags = @raw_omegas;
410 # ## Collect the diagonals
411 # foreach $i (0..$#raw_omegas) {
412 # if( $self -> _isdiagonal('index' => $i+1) ){
413 # push( @diags, $raw_omegas[$i] );
418 # foreach $i (0..$#raw_omegas){
419 # if($self -> _isdiagonal('index' => $i+1)) {
420 # if( $raw_omegas[$i] <= 0 ){
421 # push( @computed_omegas, $raw_omegas[$i] );
424 # push @computed_omegas, sqrt($raw_omegas[$i]);
427 # @indices = $self -> _rowcolind( index => $i+1 );
428 # if( ($raw_omegas[$i] == 0) or ($diags[$indices[0]-1]*$diags[$indices[1]-1]) <= 0 ) {
431 # push @computed_omegas,
432 # $raw_omegas[$i]/sqrt($diags[$indices[0]-1]*$diags[$indices[1]-1]);
436 # $self -> {'comegas'}= \@computed_omegas;}
440 # {{{ _compute_csigmas
441 start _compute_csigmas
443 $self -> _compute_comegas_or_csigmas
( omega_or_sigma
=> 'sigma' );
446 # This is the old algoritm for transforming sigmass. It can't handle
447 # of-diagonals sigmass that are zero, if that should ever happen.
450 # if (defined $self -> {'raw_sigmas'} ) {
452 # my ( @om, @com, @diags, @indices );
453 # @om = @{$self -> {'raw_sigmas'}};
455 # ## Collect the diagonals
456 # foreach $i (0..$#om) {
457 # push @diags,$om[$i] if $self -> _isdiagonal('index' => $i+1);
459 # foreach $i (0..$#om){
460 # if($self -> _isdiagonal('index' => $i+1)) {
461 # if( $om[$i] <= 0 ){
464 # push @com, sqrt($om[$i]);
467 # @indices = $self -> _rowcolind( index => $i+1 );
468 # if( ($om[$i] == 0) or ($diags[$indices[0]-1]*$diags[$indices[1]-1] <= 0) ) {
472 # $om[$i]/sqrt($diags[$indices[0]-1]*$diags[$indices[1]-1]);
476 # $self -> {'csigmas'}= \@com;
480 # }}} _compute_csigmas
482 # {{{ _compute_cvseomega
484 start _compute_cvseomega
486 if( defined $self -> raw_omegas
() and defined $self -> raw_seomegas
() ) {
487 my @raw_omegas = @
{$self -> raw_omegas
()};
488 my @raw_seomegas = @
{$self -> raw_seomegas
()};
491 if ( scalar @raw_seomegas > 0) {
493 my ( @init_om, @init_seom );
495 foreach $i (0.. $#raw_seomegas){
496 if( $self -> _isdiagonal
('index' => $i+1)) {
497 push @init_seom, $raw_seomegas[$i];
500 if(($raw_seomegas[$i] eq 'NA') or ($raw_seomegas[$i] == 0)) {
503 push @init_seom, $raw_seomegas[$i];
508 foreach $i (0..$#raw_omegas){
509 if( $self -> _isdiagonal
('index' => $i+1)) {
510 push @init_om, $raw_omegas[$i];
513 if($raw_omegas[$i] == 0) {
516 push @init_om, $raw_omegas[$i];
521 foreach my $i (0..$#init_om) {
522 if( $init_seom[$i] ne 'NA' and $init_om[$i] ne 'NA' ){
523 if( ($init_seom[$i] == 'INF' or $init_seom[$i] == '-INF') and
524 ($init_om[$i] == 'INF' or $init_om[$i] == '-INF') ) {
525 push @cvseomega,undef;
526 } elsif ( $init_seom[$i] == 'INF' ) {
527 push @cvseomega,'INF';
528 } elsif ( $init_seom[$i] == '-INF' ) {
529 push @cvseomega,'-INF';
530 } elsif ( $init_om[$i] == 'INF' or
531 $init_om[$i] == '-INF' ) {
534 push @cvseomega,$init_seom[$i]/abs($init_om[$i]);
537 push @cvseomega,undef;
539 # push @cvseomega,$init_seom[$i]/$init_om[$i]
540 # if ($init_seom[$i] && $init_om[$i]);
541 # push @cvseomega,"NA" unless ($init_seom[$i] && $init_om[$i]);
546 $self -> cvseomegas
([@cvseomega]);
549 end _compute_cvseomega
551 # }}} _compute_cvseomega
553 # {{{ _compute_cvsesigma
554 start _compute_cvsesigma
556 if( defined $self -> raw_sigmas
() and defined $self -> raw_sesigmas
() ) {
557 my @raw_sigmas = @
{$self -> raw_sigmas
()};
558 my @raw_sesigmas = @
{$self -> raw_sesigmas
()};
561 if ( scalar @raw_sesigmas > 0) {
563 my ( @init_si, @init_sesi );
565 foreach $i (0.. $#raw_sesigmas){
566 if($self -> _isdiagonal
('index' => $i+1)) {
567 push @init_sesi, $raw_sesigmas[$i];
570 if(($raw_sesigmas[$i] eq 'NA') or ($raw_sesigmas[$i] == 0)) {
573 push @init_sesi, $raw_sesigmas[$i];
578 foreach $i (0.. $#raw_sigmas){
579 if($self -> _isdiagonal
('index' => $i+1)) {
580 push @init_si, $raw_sigmas[$i];
583 if($raw_sigmas[$i] == 0) {
586 push @init_si, $raw_sigmas[$i];
591 foreach my $i (0..$#init_si) {
592 if( $init_sesi[$i] ne 'NA' and $init_si[$i] ne 'NA' ){
593 if( ($init_sesi[$i] == 'INF' or $init_sesi[$i] == '-INF') and
594 ($init_si[$i] == 'INF' or $init_si[$i] == '-INF') ) {
595 push @cvsesigma,undef;
596 } elsif ( $init_sesi[$i] == 'INF' ) {
597 push @cvsesigma,'INF';
598 } elsif ( $init_sesi[$i] == '-INF' ) {
599 push @cvsesigma,'-INF';
600 } elsif ( $init_si[$i] == 'INF' ) {
603 push @cvsesigma,$init_sesi[$i]/abs($init_si[$i]);
606 push @cvsesigma,undef;
612 $self -> cvsesigmas
([@cvsesigma]);
615 end _compute_cvsesigma
616 # }}} _compute_cvsesigma
618 # {{{ _compute_cvsetheta
619 start _compute_cvsetheta
621 if( defined $self -> thetas
() and defined $self -> sethetas
() ) {
622 my @thetas = @
{$self -> thetas
()};
623 my @sethetas = @
{$self -> sethetas
()};
626 if ( scalar @sethetas > 0 ) {
627 foreach my $i (0..$#thetas) {
628 if( defined $sethetas[$i] and
629 defined $thetas[$i] ) {
630 if( $thetas[$i] != 0 ) {
631 push(@cvsethetas,$sethetas[$i]/abs($thetas[$i]));
632 } elsif( $sethetas[$i] > 0 ) {
633 push(@cvsethetas,'INF');
635 push(@cvsethetas,'-INF');
638 push @cvsethetas,"NA";
643 $self -> cvsethetas
([@cvsethetas]);
646 end _compute_cvsetheta
647 # }}} _compute_cvsetheta
654 return(1) if $index == 1;
655 foreach my $j (2..100) {
656 return(1) if $index == $previ+$j;
658 last if $index < $previ;
664 # {{{ _read_matrixoestimates
665 start _read_matrixoestimates
667 # Reads one matrix structure and returns the file handle at
668 # the beginning of the next structure
669 while ( $_ = @
{$self -> {'lstfile'}}[ $pos++ ] ) {
671 # Rewind one step if we find something that marks the end of
673 $pos-- and last if ( /^ PROBLEM.*SUBPROBLEM/ or /^ PROBLEM NO\.:\s+\d/ );
674 $pos-- and last if (/^[a-df-zA-DF-Z]/);
676 next if ( /^\s+TH/ or /^\s+OM/ or /^\s+SG/ ); # Header row
677 next if ( /^1/ ); # Those annoying 1's
679 chomp; # Get rid of line-feed
681 shift( @row ) if ( $row[0] eq '+' ); # Get rid of +-sign
683 next if ( $#row < 0 ); # Blank row
685 push( @subprob_matrix, @row );
687 $success = 1 if( scalar @subprob_matrix > 0 );
689 end _read_matrixoestimates
690 # }}} _read_matrixoestimates
692 # {{{ _read_covmatrix
693 start _read_covmatrix
696 my ( $t_success, $c_success, $corr_success, $i_success ) = (0,0,0,0);
697 my $start_pos = $self -> {'lstfile_pos'}-1;
703 my @matrix = @
{$m_ref};
704 # get rid of '........'
706 foreach ( @matrix ) {
707 unless ( $_ eq '.........' ) {
710 } elsif ( $_ eq 'INF' ) {
711 push( @clear, 99999999999999 );
712 } elsif ( $_ eq '-INF' ) {
713 push( @clear, -99999999999999 );
724 # {{{ sub make square
728 my @matrix = @
{$m_ref};
729 # Make the matrix square:
730 my $elements = scalar @matrix; # = M*(M+1)/2
731 my $M = -0.5 + sqrt( 0.25 + 2 * $elements );
733 for ( my $m = 1; $m <= $M; $m++ ) {
734 for ( my $n = 1; $n <= $m; $n++ ) {
735 push( @
{$square[$m-1]}, $matrix[($m-1)*$m/2 + $n - 1] );
736 unless ( $m == $n ) {
737 push( @
{$square[$n-1]}, $matrix[($m-1)*$m/2 + $n - 1] );
746 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
748 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
749 if (/^ TH (\d)/ or /^\s+TH (\d) \| /) { # Read matrix and get out of inner while loop
750 ( $start_pos, $self -> {'raw_tmatrix'}, $t_success ) = $self ->
751 _read_matrixoestimates
( pos => $start_pos ) and last;
754 last; # No covariance matrix will be found!
756 if (/ COVARIANCE MATRIX OF ESTIMATE/) {
757 while( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
758 if (/^ TH (\d)/ or /^\s+TH (\d) \| /) { # Read matrix and get out of inner while loop
759 ( $start_pos, $self -> {'raw_covmatrix'}, $c_success ) = $self ->
760 _read_matrixoestimates
( pos => $start_pos ) and last;
764 if (/ CORRELATION MATRIX OF ESTIMATE/) {
765 while( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
766 if (/^ TH (\d)/ or /^\s+TH (\d) \| /) { # Read matrix and get out of inner while loop
767 ( $start_pos, $self -> {'raw_cormatrix'}, $corr_success ) = $self ->
768 _read_matrixoestimates
( pos => $start_pos ) and last;
772 if (/ INVERSE COVARIANCE MATRIX OF ESTIMATE/) {
773 while( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
774 if (/^ TH (\d)/ or /^\s+TH (\d) \| /) { # Read matrix and get out of inner while loop
775 ( $start_pos, $self -> {'raw_invcovmatrix'}, $i_success ) = $self ->
776 _read_matrixoestimates
( pos => $start_pos ) and last;
782 foreach my $element ( @
{$self -> {'raw_tmatrix'}} ) {
783 push( @
{$self -> {'t_matrix'}}, eval($element) ) unless ( $element eq '.........' );
785 foreach my $element ( @
{$self -> {'raw_covmatrix'}} ) {
786 push( @
{$self -> {'covariance_matrix'}}, eval($element) ) unless ( $element eq '.........' );
788 foreach my $element ( @
{$self -> {'raw_cormatrix'}} ) {
789 push( @
{$self -> {'correlation_matrix'}}, eval($element) ) unless ( $element eq '.........' );
792 if( defined $self -> {'raw_invcovmatrix'} ) {
793 $self -> {'inverse_covariance_matrix'} = Math
::MatrixReal
->
794 new_from_cols
( make_square
( clear_dots
( $self -> {'raw_invcovmatrix'} ) ) );
797 # foreach my $element ( @{$self -> {'raw_invcovmatrix'}} ) {
798 # push( @{$self -> {'inverse_covariance_matrix'}}, eval($element) ) unless ( $element eq '.........' );
801 #If something has gone right!
802 $self-> {'lstfile_pos'} = $start_pos if ( $t_success + $c_success + $corr_success + $i_success );
805 # }}} _read_covmatrix
812 my $start_pos = $self -> {'lstfile_pos'};
814 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
816 if ( /EIGENVALUES OF COR MATRIX OF ESTIMATE/ ) {
818 $start_pos = $start_pos + 4 ; # Jump forward to the index numbers
819 debug
-> warn( level
=> 2,
820 message
=> "Found the eigenvalue area" );
821 INNER
: while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) { # Get rid of indexes
822 last INNER
if ( not /^\s+\d/ );
823 # $start_pos++ and last INNER if ( not /^\s+\d/ );
827 $start_pos-- and last if (/^[a-df-zA-DF-Z]/); #Rewind one step
828 last if ( /^\s*\*/ or /^1/ );
829 push( @eigens, split );
831 $start_pos-- and last if ( /^ PROBLEM.*SUBPROBLEM/ or /^ PROBLEM NO\.:\s+\d/ );
832 $start_pos-- and last if (/^[a-df-zA-DF-Z]/); #Rewind one step
834 if ( scalar @eigens > 0 ) {
835 my @list = sort { $a <=> $b } @eigens;
836 $self -> {'condition_number'} = abs($list[$#list]/$list[0]) if ( $list[0] != 0 );
838 @
{$self -> {'eigens'}} = @eigens;
847 my $start_pos = $self -> {'lstfile_pos'};
849 while( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
850 if ( / PROBLEM NO\.:\s*\d+\n/ ) {
851 $self -> parsing_error
( message
=> "Error in reading the number of ".
852 "function evaluations!\nNext problem found" );
856 if ( $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
857 $self -> parsing_error
( message
=> "Error in reading number of ".
858 "function evaluations!\nEOF found\n" );
862 if ( /^1/ or /MINIMUM VALUE OF OBJECTIVE FUNCTION/ ) {
863 $self -> parsing_error
( message
=> "Error in reading number of ".
864 "function evaluations!\nOFV found" );
868 if ( / NO. OF FUNCTION EVALUATIONS USED:\s*(\d*)/ ){
877 # {{{ _read_iteration_path
878 start _read_iteration_path
880 my $start_pos = $self -> {'lstfile_pos'};
882 my (@func_eval, @parameter_vectors,
883 @gradient_vectors) = ((), (), (), (), ());
884 my @numsigdig_vectors;
885 my $cumulative_evals = 0;
886 my $zero_gradients = 0;
887 my $hessian_reset = 0;
888 my $found_monitoring = 0;
889 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) { #Large reading loop
890 if ( /MONITORING OF SEARCH/ ) {
891 $found_monitoring = 1;
894 if ( $found_monitoring and
895 $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
896 # This is probably (we cannot be really sure but it is
897 # likely) a "NONMEM black hole"-situation. We stop parsing
898 # but do not indicate that we had problems parsing the
900 $self -> parsing_error_message
("Found \" MONITORING OF SEARCH:\" but no".
901 " records of the iterations before the end".
902 " of the output file. This is a sign of a".
903 " \"NONMEM black hole\"-situation. We cannot ".
904 "be 100% sure of this based on this type of".
905 " output so please take a good look at the files\n");
906 $self -> parsed_successfully
(1);
907 $self -> finished_parsing
(1);
911 if ( /0PROGRAM TERMINATED BY OBJ/ ) {
912 # This is an error message which terminates NONMEM. We
913 # return after reading the minimization message
914 $self -> minimization_successful
(0);
915 $self -> _read_minimization_message
();
916 $self -> finished_parsing
(1);
920 if (/^0ITERATION NO/) {
921 unless (/0ITERATION NO\.:\s+(\d+)\s+OBJECTIVE VALUE:\s+(\S+)\s+NO\. OF FUNC\. EVALS\.:\s*(.+)/) {
922 $self -> parsing_error
( message
=> "Error in reading iteration path!\n$!" );
926 push(@
{$self -> {'iternum'}}, $1);
929 unless( $ofvpath eq '**' ){ # If funcion evals are more than 10000, NONMEM will print out two stars.
930 push(@
{$self -> {'ofvpath'}}, $ofvpath );
931 } # If, in fact, we find stars, the number of evaluations are calculated below
933 my (@parameter_vector, @gradient_vector) = ((), ());
934 my @numsigdig_vector;
936 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos ] ) {
937 if (/^ CUMULATIVE NO\. OF FUNC\. EVALS\.:\s*(\d+)/) {
940 if( $ofvpath eq '**' ){
941 my $ofvpath = $eval_path - $cumulative_evals;
942 $cumulative_evals = $eval_path;
943 debug
-> warn( level
=> 2,
944 message
=> "Calculated eval_path = $ofvpath" );
945 push(@
{$self -> {'ofvpath'}}, $ofvpath );
948 push(@
{$self -> {'funcevalpath'}}, $eval_path);
950 if (/RESET HESSIAN, TYPE (\w+)/) {
955 } elsif ( s/^ PARAMETER:\s*// ) {
957 push(@parameter_vector, split);
958 $_ = @
{$self -> {'lstfile'}}[ ++$start_pos ];
959 if( $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
960 $self -> parsing_error
( message
=> "Error in reading iteration path!\nEOF found\n" );
963 } while ( not /^ GRADIENT:\s*/ );
964 } elsif (s/^ GRADIENT:\s*//) {
966 push(@gradient_vector, split);
967 $_ = @
{$self -> {'lstfile'}}[ ++$start_pos ];
968 if( $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
969 $self -> parsing_error
( message
=> "Error in reading iteration path!\nEOF found\n" );
972 } while ( not /[A-D][F-X]/ );
973 } elsif (s/^ NUMSIGDIG:\s*//) {
975 push(@numsigdig_vector, split);
976 $_ = @
{$self -> {'lstfile'}}[ ++$start_pos ];
977 if( $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
978 $self -> parsing_error
( message
=> "Error in reading iteration path!\nEOF found\n" );
981 } while ( not /[A-D][F-X]/ );
986 foreach my $grad ( @gradient_vector ) {
987 $zero_gradients++ if $grad == 0;
989 $self -> {'initgrad'} = \
@gradient_vector unless($self -> {'initgrad'});
990 $self -> {'final_gradients'} = \
@gradient_vector;
991 $self -> {'finalparam'} = \
@parameter_vector;
992 push(@parameter_vectors, \
@parameter_vector);
993 push(@gradient_vectors, \
@gradient_vector);
994 $self -> {'parameter_significant_digits'} = \
@numsigdig_vector if scalar @numsigdig_vector;
996 if( /0HESSIAN OF POSTERIOR DENSITY IS NON-POSITIVE-DEFINITE DURING SEARCH/ ) {
997 # This is an errror that stops the execution
998 $self -> finished_parsing
(1);
1001 last unless(/^0ITERATION NO/);
1002 } #End of if iteration no
1003 } #End of large reading loop
1005 unless( $self -> finished_parsing
() ) {
1006 my ($kill_found, $file_end, $kill_message, $search_pos) = (0, 0, "", $start_pos);
1007 while ( $_ = @
{$self -> {'lstfile'}}[ $search_pos++ ] ) { #Have a look, a few lines down...
1013 # $kill_found = 1 and $kill_message = $_ and last if(/kill/i);
1014 if( $search_pos + 1 == scalar @
{$self -> {'lstfile'}} ) {
1016 $search_pos = $start_pos + 4;
1018 last if( $search_pos > $start_pos + 3 )
1019 # last if (--$kill_found < -2);
1021 if (($kill_found == 1) or $file_end) { #Crash before last iteration
1022 my $errstr = $kill_found ?
"NONMEM killed" : "EOF found\n";
1023 $self -> parsing_error
( message
=> "Error in reading iteration path!\n$errstr" );
1026 # $self -> {'minimization_message'} = ["PsN message:","The output file seems to have an abrupt ending," .
1027 # " before the last","iteration has finished."];
1028 # if ($kill_found == 1) {
1029 # push(@{$self -> {'minimization_message'}}, "String found in output file: $kill_message" );
1031 # push(@{$self -> {'minimization_message'}}, " This is probably due to a crash");
1036 unless ( $success ){
1037 debug
-> warn( level
=> 2,
1038 message
=> "rewinding to first position..." );
1040 $self -> {'lstfile_pos'} = $start_pos;
1041 $self -> {'parameter_path'} = \
@parameter_vectors;
1042 $self -> {'gradient_path'} = \
@gradient_vectors;
1043 $self -> {'zero_gradients'} = $zero_gradients;
1044 my $final_zero_gradients = 0;
1045 foreach my $grad ( @
{$self -> {'final_gradients'}} ) {
1046 $final_zero_gradients++ if $grad == 0;
1048 $self -> {'final_zero_gradients'} = $final_zero_gradients;
1049 $self -> {'hessian_reset'} = $hessian_reset;
1052 end _read_iteration_path
1053 # }}} _read_iteration_path
1055 # {{{ _read_npomegas
1057 start _read_npomegas
1059 my $start_pos = $self -> {'lstfile_pos'};
1063 my $npetabararea = 0;
1065 my ( @npetabar, @npomega, @T, $i );
1067 while( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
1068 $nparea = 1 if /NONPARAMETRIC ESTIMATE/;
1069 last if ( /THERE ARE ERROR MESSAGES IN FILE PRDERR/ and $nparea );
1070 last if ( /^1/ and $nparea );
1071 last if ( /^1NONLINEAR/ and $nparea );
1072 last if ( /^[A-W]/ and $nparea );
1074 if (/MINIMUM VALUE OF OBJECTIVE FUNCTION/ and $nparea ){ #Only nonmem6 version
1077 if ( /EXPECTED VALUE OF ETA/ and $nparea ) {
1082 if ( /COVARIANCE MATRIX OF ETA/ and $nparea ) {
1086 if($npofvarea and /^\s+(-?\d*\.\d*)/) { #Assignment of attribute at the spot
1087 $self -> {'npofv'} = $1;
1090 if($npetabararea and /^\s*-?\d*\.\d*/) {
1092 for $i (0..(@T-1)) {$T[$i] = eval($T[$i]);}
1095 if($npomegarea and /^(\+|\s{2,})/) {
1098 shift @T if $T[0] eq '+';
1099 for $i (0..(@T-1)) {$T[$i] = eval($T[$i]);}
1103 $self -> {'npetabar'} = [@npetabar];
1104 $self -> {'npomegas'} = [@npomega];
1105 unless ( $success ) {
1106 debug
-> warn( level
=> 2,
1107 message
=> "rewinding to first position..." );
1109 $self -> {'lstfile_pos'} = $start_pos;
1114 # }}} _read_npomegas
1120 my $start_pos = $self -> {'lstfile_pos'};
1122 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
1123 if ( / PROBLEM NO\.:\s*\d+\n/ ) {
1124 $self -> parsing_error
( message
=> "Error in reading ".
1125 "the OFV!\nNext problem found" );
1129 if ( $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
1130 $self -> parsing_error
( message
=> "Error in reading ".
1131 "the OFV!\nEOF found\n" );
1135 if ( /^\s\*{50}\s+/ ) {
1136 (undef, my $ofvt, undef) = split(' ',$_,3);
1137 if ( $ofvt =~ /\*\*\*\*\*\*/ ) {
1138 $self -> {'ofv'} = undef;
1140 $self -> ofv
($ofvt);
1145 $self -> {'lstfile_pos'} = $start_pos;
1156 while ( not $found ) {
1157 my $test = $index - ($i-1)*($i)/2;
1158 if ( $test <= $i ) {
1166 # my @startind = (2,5,9,14,20,27,35,44);
1170 # OUTER: foreach $col (1..8) {
1171 # $prevind = $startind[$col-1];
1172 # foreach $row (($col+1)..8) {
1174 # ## If this is the first element of the column
1175 # if($index == $prevind) {
1179 # ## If it is a later element in the column
1180 # if($index == $prevind+$row) {
1181 # # print "$index $col ",$row+1," ",$startind[$col-1],"\n" ;
1185 # $prevind = $prevind+$row;
1190 # print "$index ",$row," $col\n";
1196 # {{{ _read_significant_digits
1197 start _read_significant_digits
1199 my $start_pos = $self -> {'lstfile_pos'};
1201 while( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
1202 if ( / PROBLEM NO\.:\s*\d+\n/ ) {
1203 $self -> parsing_error
( message
=> "Error in reading the number of ".
1204 "significant digits!\nNext problem found" );
1208 if ( $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
1209 $self -> parsing_error
( message
=> "Error in reading the number of ".
1210 "significant digits!\nEOF found\n" );
1214 if ( /^1/ or /MINIMUM VALUE OF OBJECTIVE FUNCTION/ ) {
1215 $self -> parsing_error
( message
=> "Error in reading the number of ".
1216 "significant digits!\nOFV found" );
1220 if ( / NO. OF SIG. DIGITS UNREPORTABLE/ ) {
1225 if ( / NO. OF SIG. DIGITS IN FINAL EST.:\s*(-?\d*\.*\d*)/ ){
1226 $self -> significant_digits
($1);
1230 $self -> {'lstfile_pos'} = $start_pos;
1232 end _read_significant_digits
1233 # }}} _read_significant_digits
1235 # {{{ _read_sethomsi
1236 start _read_sethomsi
1238 my $start_pos = $self -> {'lstfile_pos'};
1244 my ( @setheta, @seomega, @sesigma, @T, $i, $tmp );
1245 my ( @raw_setheta, @raw_seomega, @raw_sesigma );
1247 # _read_thomsi should leave us right at where we should start reading
1248 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
1250 if ( ($omegarea or $sigmarea ) and
1251 /COVARIANCE MATRIX OF ESTIMATE/ ) {
1252 # This is fine, we should end up here after reading the
1260 # This is also fine, if those matrices were output, we
1261 # should end up here before we could start reading the
1267 if ( /NONPARAMETRIC ESTIMATE/ ) {
1268 # This is also fine. If the nonparametric step is run, we
1269 # should end up here regardless of the termination status
1270 # of the covariance step.
1275 if ( /^1NONLINEAR/ ) {
1276 $self -> parsing_error
( message
=> "Error in reading the standard error of the parameter ".
1277 "estimates!\nFound: $_" );
1281 if ( /THERE ARE ERROR MESSAGES IN FILE PRDERR/ ) {
1282 # This is an NONMEM error message and is ok (to find), but
1283 # it means that we can stop parsing the file
1284 $self -> finished_parsing
(1);
1288 if ( /THETA - VECTOR OF FIXED EFFECTS PARAMETERS/ ) {
1291 if ( /OMEGA - COV MATRIX FOR RANDOM EFFECTS - ETAS/ ) {
1295 if ( /SIGMA - COV MATRIX FOR RANDOM EFFECTS - EPSILONS/ ) {
1301 # last if ( / COVARIANCE MATRIX OF ESTIMATE/ );
1302 # last if ( /THERE ARE ERROR MESSAGES IN FILE PRDERR/ );
1303 # The row below checking for a one '1', crashes behaviour with MANY etas (>15)
1305 # last if ( /^[A-W]/ and $searea );
1307 if ( $thetarea and /^\s*-?\d*\.\d*/ ) {
1309 for $i (0..(@T-1)) {
1310 $T[$i] = eval($T[$i]);
1314 if($omegarea and /^(\+|\s{2,})/) {
1317 shift @T if $T[0] eq '+';
1318 if ( not defined $self -> {'omega_block_structure'} ) {
1319 for $i (0..(@T-1)) {
1320 if(($T[$i] ne '.........') and (eval($T[$i]) != 0) ) {
1321 push(@seomega,eval($T[$i]));
1325 for $i (0..(@T-1)) {
1326 if($T[$i] ne '.........') {
1327 $tmp = eval($T[$i]);
1333 push(@raw_seomega,@T);
1336 if($sigmarea and /^(\+|\s{2,})/) {
1339 shift @T if $T[0] eq '+';
1340 if ( not defined $self -> {'sigma_block_structure'} ) {
1341 for $i (0..(@T-1)) {
1342 if(($T[$i] ne '.........') and (eval($T[$i]) != 0) ) {
1343 push(@sesigma,eval($T[$i]));
1347 for $i (0..(@T-1)) {
1348 if ($T[$i] ne '.........') {
1349 $tmp = eval($T[$i]);
1355 push(@raw_sesigma,@T);
1358 if ( $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
1359 $self -> parsing_error
( message
=> "Error in reading the standard error of the parameter ".
1360 "estimates!\nEOF found\n" );
1366 if ( defined $self -> {'omega_block_structure'} ) {
1367 my @omblock = @
{$self -> {'omega_block_structure'}};
1368 debug
-> warn( level
=> 2,
1369 message
=> "OMEGA BLOCK DEFINED" ) if ( scalar @omblock > 0 );
1372 foreach my $row ( @omblock ) {
1373 foreach my $element ( @
{$row} ) {
1374 push ( @seomega, $raw_seomega[$i] ) if ( $element );
1380 if ( defined $self -> {'sigma_block_structure'} ) {
1381 my @siblock = @
{$self -> {'sigma_block_structure'}};
1384 debug
-> warn( level
=> 2,
1385 message
=> "SIGMA BLOCK DEFINED" ) if ( scalar @siblock > 0 );
1386 foreach my $row ( @siblock ) {
1387 foreach my $element ( @
{$row} ) {
1388 push ( @sesigma, $raw_sesigma[$i] ) if ( $element );
1394 $self -> {'sethetas'} = [@setheta];
1395 $self -> {'raw_seomegas'} = [@raw_seomega];
1396 $self -> {'raw_sesigmas'} = [@raw_sesigma];
1397 $self -> {'seomegas'} = [@seomega];
1398 $self -> {'sesigmas'} = [@sesigma];
1400 if ( scalar @setheta <= 0 ) {
1401 $self -> {'covariance_step_successful'} = 0;
1403 $self -> {'covariance_step_successful'} = 1;
1406 unless ( $success ) {
1407 debug
-> warn( level
=> 2,
1408 message
=> "No standard errors for thetas, sigmas or omegas." );
1410 $self -> {'lstfile_pos'} = $start_pos;
1414 # }}} _read_sethomsi
1416 # {{{ _read_simulation
1417 start _read_simulation
1419 # The simulation step is optional.
1420 my $start_pos = $self -> {'lstfile_pos'};
1421 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos ++ ] ) {
1422 if ( /MINIMUM VALUE OF OBJECTIVE FUNCTION/ ) {
1425 if ( /^\s*MONITORING OF SEARCH:/) {
1428 if ( /\s*SIMULATION STEP PERFORMED/ ) {
1429 $self ->{'simulationstep'} = 1;
1434 if ( $self -> {'simulationstep'} ) {
1435 $self -> {'lstfile_pos'} = $start_pos;
1438 end _read_simulation
1439 # }}} _read_simulation
1445 my $start_pos = $self -> {'lstfile_pos'};
1448 my $pred_exit_code = 0;
1450 $self -> minimization_successful
(0);
1451 # if ( $self -> {'covariance_step_run'} ) {
1452 # $self -> covariance_step_successful(1);
1453 # # If there are problems in the cov-step they will be caught later
1455 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
1456 $self -> {'s_matrix_singular'} = 1 if ( /^0S MATRIX ALGORITHMICALLY SINGULAR/ );
1457 if ( /^0R MATRIX ALGORITHMICALLY SINGULAR/ or
1458 /^0S MATRIX ALGORITHMICALLY SINGULAR/ ) {
1459 $self -> covariance_step_warnings
(1);
1462 if ( /^0ESTIMATE OF THETA IS NEAR THE BOUNDARY AND/ or
1463 /0PARAMETER ESTIMATE IS NEAR ITS BOUNDARY/ ) {
1464 $self -> estimate_near_boundary
(1);
1467 if ( /ROUNDING ERRORS/ ) {
1468 $self -> rounding_errors
(1);
1471 if ( /0COVARIANCE STEP ABORTED/ ) {
1472 $self -> covariance_step_run
(0);
1476 if ( / THIS MUST BE ADDRESSED BEFORE THE COVARIANCE STEP CAN BE IMPLEMENTED/ ) {
1477 $self -> covariance_step_run
(0);
1481 # "0ERROR RMATX- 1" should (if it exists) occur after the minim. succ message
1482 if ( /0ERROR RMATX- 1/ ) {
1483 $self -> minimization_successful
(0);
1487 if ( /^0MINIMIZATION SUCCESSFUL/ ) {
1488 $self -> minimization_successful
(1);
1490 $self -> {'lstfile_pos'} = $start_pos-1;
1494 if ( /^0MINIMIZATION TERMINATED/ ) {
1495 $self -> minimization_successful
(0);
1496 $self -> covariance_step_run
(0);
1498 $self -> {'lstfile_pos'} = $start_pos-1;
1502 if ( /^0SEARCH WITH ESTIMATION STEP WILL NOT PROCEED/ ) {
1503 $self -> minimization_successful
(0);
1504 $self -> covariance_step_run
(0);
1506 $self -> finished_parsing
(1);
1510 if ( /0PRED EXIT CODE = 1/ ) {
1511 # This is an error message but the severity of it depends
1512 # on the origin of it
1513 $pred_exit_code = 1;
1517 if ( $pred_exit_code and
1518 /MESSAGE ISSUED FROM SIMULATION STEP/ ) {
1520 # These are probably not needed if we match the sim. step string above
1521 # /ERROR IN TRANS4 ROUTINE: (.*) IS ZERO/ or
1522 # /ERROR IN TRANS4 ROUTINE: (.*) IS NEGATIVE/ ) ) {
1524 # This is an error message which terminates NONMEM. We
1525 # return after reading the minimization message
1526 $self -> minimization_successful
(0);
1527 $self -> _read_minimization_message
();
1528 $self -> finished_parsing
(1);
1532 if ( /0PROGRAM TERMINATED BY OBJ/ ) {
1533 # This is an error message which terminates NONMEM. We
1534 # return after reading the minimization message
1535 $self -> minimization_successful
(0);
1536 $self -> _read_minimization_message
();
1537 $self -> finished_parsing
(1);
1541 if ( /MINIMUM VALUE OF OBJECTIVE FUNCTION/ ) {
1542 debug
-> warn( level
=> 2,
1543 message
=> "Hmmm, reached the OFV area" );
1548 debug
-> warn( level
=> 2,
1549 message
=> "Found a minimization statement" );
1550 $self -> _read_minimization_message
();
1551 $self -> _read_eval
() if ($self -> parsed_successfully
());
1552 $self -> _read_significant_digits
() if ($self -> parsed_successfully
());
1554 debug
-> warn( level
=> 1,
1555 message
=> "No minimization/termination statement found" ); #Back to starting line
1556 $self -> parsing_error
( message
=> "Error in reading minim/term statement!\n$!" );
1564 # {{{ _read_minimization_message
1566 start _read_minimization_message
1568 # This method is called from _read_term() and the listfile_pos
1569 # variable should leave us right at the start of the
1570 # minimization message. _read_eval() and
1571 # _read_significant_digits() are called after this method so
1572 # we need to rewind to our starting position
1574 my (@mess, @etabar,@pval);
1577 my $start_pos = $self -> {'lstfile_pos'};
1578 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
1579 if ( / PROBLEM NO\.:\s*\d+\n/ ) {
1580 $self -> parsing_error
( message
=> "Error in reading minimization ".
1581 "message!\nNext problem found" );
1585 if ( $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
1586 $self -> parsing_error
( message
=> "Error in reading minimization ".
1587 "message!\nEOF found\n" );
1591 if ( /^1/ or /MINIMUM VALUE OF OBJECTIVE FUNCTION/ ) {
1592 # This is ok. We would expect to end up here probably
1593 # catching the '1' above
1594 debug
-> warn( level
=> 2,
1595 message
=> "Found minimization area and reached ".$_ );
1602 push( @
{$self -> {'minimization_message'}}, @mess );
1605 my $etabar_found = 0;
1606 for( my $i=0;$i<=$#mess;$i++ ){
1607 my $line = $mess[$i];
1609 if ( $etabar_found or ($line =~ /\s+ETABAR:\s+/) ) {
1611 $line =~ s/ETABAR://;
1613 last unless ( $line =~ s/^\s+//);
1614 last unless ( $line =~ /\d/);
1615 last if( $line =~ /^1/);
1616 last if( $line =~ /[a-zA-DF-Z]/);
1618 @temp = split(/\s+/,$line);
1619 push @etabar, @temp;
1622 # Initialize the attribute only if we have found any data
1623 $self -> {'etabar'} = \
@etabar if ( $#etabar > 0 );
1626 for( my $i=0;$i<=$#mess;$i++ ){
1627 my $line = $mess[$i];
1628 if ( $pval_found or ($line =~ /\s+P VAL\.:\s+/ ) ) {
1630 $line =~ s/P VAL\.://;
1632 last unless ( $line =~ s/^\s+//);
1633 last unless ( $line =~ /\d/);
1634 last if( $line =~ /^1/);
1635 last if( $line =~ /[a-zA-DF-Z]/);
1636 @temp = split(/\s+/,$line);
1641 $self -> {'pval'} = \
@pval;
1643 unless ( $success ) {
1644 debug
-> warn( level
=> 2,
1645 message
=> "No minimization message found" );
1648 end _read_minimization_message
1650 # }}} _read_minimization_message
1656 my $start_pos = $self -> {'lstfile_pos'};
1662 my ( @theta, @omega, @raw_omega, @sigma, @raw_sigma, @T, $i, $tmp );
1664 # _read_ofv should leave us right at where we should start reading
1665 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
1667 if ( ($omegarea or $sigmarea ) and
1668 # For some reason, NONMEM prints a '1' (i.e. /^1$/)
1669 # after the thirteenth omega row. I other words, we
1670 # cannot use /^1$/ as check for omega area ending.
1673 /STANDARD ERROR OF ESTIMATE/ or
1674 /NONPARAMETRIC ESTIMATE/ or
1677 /TABLES OF DATA AND PREDICTIONS/ )) {
1678 # This is fine, we should end up here after reading the estimates
1683 if ( /^1NONLINEAR/ ) {
1684 $self -> parsing_error
( message
=> "Error in reading the parameter ".
1685 "estimates!\nFound: $_" );
1689 if ( /THERE ARE ERROR MESSAGES IN FILE PRDERR/ ) {
1690 # This is an NONMEM error message and is ok (to find), but
1691 # it means that we can stop parsing the file
1692 $self -> finished_parsing
(1);
1696 if ( /THETA - VECTOR OF FIXED EFFECTS PARAMETERS/ ) {
1699 if ( /OMEGA - COV MATRIX FOR RANDOM EFFECTS - ETAS/ ) {
1704 if ( /SIGMA - COV MATRIX FOR RANDOM EFFECTS - EPSILONS/ ) {
1709 # The row below checking for a one '1', crashes behaviour with MANY etas (>15)
1710 # last if ( /^1/ and $estarea );
1711 # These rows should not be needed. If a valid alternative
1712 # exists, add it as a match above or raise a parsing error
1714 # last if ( /^\s+\*\*\*\*\*\*\*\*\*\*\*\*/ and ( $sigmarea or $thetarea or $omegarea ));
1715 # last if ( /^[A-W]/ and $estarea );
1717 if( $thetarea and /^\s*-?\d*\.\d*/ ) {
1719 for $i (0..(@T-1)) {
1720 $T[$i] = eval($T[$i]);
1725 if($omegarea and /^(\+|\s{2,})/) {
1728 shift @T if $T[0] eq '+';
1729 if ( $self -> {'omega_block_structure_type'} eq 'DIAGONAL' ) {
1730 for $i (0..(@T-1)) {
1731 if(($T[$i] ne '.........') and (eval($T[$i]) != 0) ) {
1732 push(@omega,eval($T[$i]));
1736 for $i (0..(@T-1)) {
1737 if($T[$i] ne '.........') {
1738 $tmp = eval($T[$i]);
1744 push(@raw_omega,@T);
1747 if($sigmarea and /^(\+|\s{2,})/) {
1751 shift @T if $T[0] eq '+';
1752 if ( $self -> {'sigma_block_structure_type'} eq 'DIAGONAL' ) {
1753 for $i (0..(@T-1)) {
1754 if(($T[$i] ne '.........') and (eval($T[$i]) != 0) ) {
1755 push(@sigma,eval($T[$i]));
1759 for $i (0..(@T-1)) {
1760 if($T[$i] ne '.........') {
1761 $tmp = eval($T[$i]);
1767 push(@raw_sigma,@T);
1770 if ( $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
1771 # This is a valid match. Sometimes, the list file ends
1772 # with the parameter estimates
1773 $self -> finished_parsing
(1);
1777 if ( $self -> {'omega_block_structure_type'} eq 'BLOCK' ) {
1778 my @omblock = @
{$self -> {'omega_block_structure'}};
1779 debug
-> warn( level
=> 2,
1780 message
=> "OMEGA BLOCK DEFINED" ) if ( scalar @omblock > 0 );
1783 foreach my $row ( @omblock ) {
1784 foreach my $element ( @
{$row} ) {
1785 push ( @omega, $raw_omega[$i] ) if ( $element );
1791 if ( $self -> {'sigma_block_structure_type'} eq 'BLOCK' ) {
1792 my @omblock = @
{$self -> {'sigma_block_structure'}};
1793 debug
-> warn( level
=> 2,
1794 message
=> "SIGMA BLOCK DEFINED" ) if ( scalar @omblock > 0 );
1797 foreach my $row ( @omblock ) {
1798 foreach my $element ( @
{$row} ) {
1799 push ( @sigma, $raw_sigma[$i] ) if ( $element );
1805 $self -> {'thetas'} = \
@theta;
1806 $self -> {'nth'} = $#theta + 1;
1807 $self -> {'raw_omegas'} = \
@raw_omega;
1808 $self -> {'nrom'} = $#raw_omega + 1;
1809 $self -> {'omegas'} = \
@omega;
1810 $self -> {'nom'} = $#omega + 1;
1811 $self -> {'raw_sigmas'} = \
@raw_sigma;
1812 $self -> {'sigmas'} = \
@sigma;
1815 # Gather the "true" estimates, i.e. for the parameters that are not fixed or SAME.
1816 foreach my $param ( 'theta', 'omega', 'sigma' ) {
1817 my @allests = eval( '@'.$param );
1819 if( $self -> msfi_used
() ) {
1820 foreach( @allests ) {
1824 @estflags = @
{$self -> {'estimated_'.$param.'s'}};
1828 # die "Something is wrong: All $param"."s: ".($#allests+1)." and estimated $param"."s: ".
1829 # ($#estflags+1)." do not match\n" unless
1830 # ( $#allests == -1 or $#estflags == $#allests );
1832 for( my $i = 0; $i <= $#allests; $i++ ) {
1833 if( $estflags[$i] ) {
1834 if ( defined $allests[$i] ) {
1835 push( @ests, $allests[$i]);
1842 $self -> {'est_'.$param.'s'} = \
@ests;
1844 # if( $#ests > -1 and $defs > 0 ) {
1845 # $self -> {'est_'.$param.'s'} = Math::MatrixReal ->
1846 # new_from_cols( [\@ests] );
1850 unless ( $success ) {
1851 debug
-> warn( level
=> 2,
1852 message
=> "No thetas, omegas or sigmas found" );
1855 # if ( $PsN::config -> {'_'} -> {'use_database'} and
1856 # $self -> {'register_in_database'} ) {
1857 # my $dbh = DBI -> connect("DBI:mysql:host=".$PsN::config -> {'_'} -> {'database_server'}.
1858 # ";databse=".$PsN::config -> {'_'} -> {'project'},
1859 # $PsN::config -> {'_'} -> {'user'},
1860 # $PsN::config -> {'_'} -> {'password'},
1861 # {'RaiseError' => 1});
1863 # my @mod_str = ('','');
1864 # if ( defined $self -> {'model_id'} ) {
1865 # @mod_str = ('model_id,',"$self->{'model_id'},");
1867 # foreach my $param ( 'theta', 'omega', 'sigma' ) {
1869 # foreach my $par_str ( eval('@'.$param) ) {
1870 # $sth = $dbh -> prepare("INSERT INTO ".$PsN::config -> {'_'} -> {'project'}.
1872 # "(subproblem_id,problem_id,output_id,".
1874 # "type,value, number, label) ".
1875 # "VALUES ( '$self->{'subproblem_id'}' ,".
1876 # "'$self->{'problem_id'}' ,".
1877 # "'$self->{'output_id'}' ,".
1879 # "'$param','$par_str', '$i', 'test_label')");
1881 # push( @{$self -> {'estimate_ids'}}, $sth->{'mysql_insertid'} );
1886 # $dbh -> disconnect;
1890 $self -> {'lstfile_pos'} = $start_pos-1;
1897 # {{{ _set_omeganames
1898 start _set_omeganames
1900 my @raw_omegas = @
{$self -> {'raw_omegas'}};
1902 unless ( scalar @raw_omegas > 0 ) {
1907 my ( @omeganames, %omeganameval, @omegas );
1910 foreach $j (1..scalar @raw_omegas) {
1911 push @omeganames, "OM".++$ndiags and next if $self -> _isdiagonal
('index' => $j);
1912 if ($raw_omegas[$j-1] !=0) {
1913 @indices = $self -> _rowcolind
( index => $j);
1914 push @omeganames,"OM".$indices[0]."\.".$indices[1];
1917 @omegas = @
{$self -> {'omegas'}};
1918 for ( my $i = 0; $i <= $#omeganames; $i++ ) {
1919 $omeganameval{$omeganames[$i]} = $omegas[$i];
1921 $self ->{'omeganameval'} = \
%omeganameval;
1922 $self ->{'omeganames'} = \
@omeganames;
1925 # }}} _set_omeganames
1927 # {{{ _set_sigmanames
1928 start _set_sigmanames
1930 my @sigmas = @
{$self -> {'raw_sigmas'}};
1931 unless ( scalar @sigmas > 0 ) {
1935 my ( @sigmanames, %sigmanameval );
1938 foreach $j (1..scalar @sigmas) {
1939 push @sigmanames, "SI".++$ndiags and next if $self -> _isdiagonal
('index' => $j);
1940 if ($sigmas[$j-1] !=0) {
1941 @indices = $self -> _rowcolind
( index => $j);
1942 push @sigmanames,"SI".$indices[0].$indices[1];
1945 @sigmas = @
{$self -> {'sigmas'}};
1946 for ( my $i = 0; $i <= $#sigmanames; $i++ ) {
1947 $sigmanameval{$sigmanames[$i]} = $sigmas[$i];
1949 $self ->{'sigmanameval'} = \
%sigmanameval;
1950 $self ->{'sigmanames'} = \
@sigmanames;
1953 # }}} _set_sigmanames
1955 # {{{ _set_thetanames
1956 start _set_thetanames
1958 my $nth = $self -> {'nth'};
1959 my ( @thetanames, %thetanameval, @thetas );
1962 push @thetanames, "TH$_";
1964 @thetas = @
{$self -> {'thetas'}};
1965 for ( my $i = 0; $i <= $#thetanames; $i++ ) {
1966 $thetanameval{$thetanames[$i]} = $thetas[$i];
1968 $self ->{'thetanameval'} = \
%thetanameval;
1969 $self ->{'thetanames'} = \
@thetanames;
1972 # }}} _set_thetanames