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
());
76 $self -> parsed_successfully
( 0 );
77 $self -> parsing_error_message
( $message );
81 # {{{ register_in_database
83 start register_in_database
84 if ( $PsN::config
-> {'_'} -> {'use_database'} ) {
85 my $dbh = DBI
-> connect("DBI:mysql:host=".$PsN::config
-> {'_'} -> {'database_server'}.
86 ";databse=".$PsN::config
-> {'_'} -> {'project'},
87 $PsN::config
-> {'_'} -> {'user'},
88 $PsN::config
-> {'_'} -> {'password'},
92 if ( defined $self->{'minimization_message'} ) {
93 $term_str = join("\n",@
{$self->{'minimization_message'}});
95 my @mod_str = ('','');
96 if ( defined $model_id ) {
97 @mod_str = ('model_id,',"$model_id,");
99 $sth = $dbh -> prepare
("INSERT INTO ".$PsN::config
-> {'_'} -> {'project'}.
101 "(problem_id,output_id,".
104 "covariance_step_successful,".
105 "covariance_step_warnings,".
107 "final_zero_gradients,".
111 "s_matrix_singular,".
112 "significant_digits,".
114 "minimization_successful,".
115 "minimization_message,".
117 "VALUES ( '$problem_id' ,".
120 "'$self->{'condition_number'}' ,".
121 "'$self->{'covariance_step_successful'}' ,".
122 "'$self->{'covariance_step_warnings'}' ,".
123 "'$self->{'eval'}' ,".
124 "'$self->{'final_zero_gradients'}' ,".
125 "'$self->{'hessian_reset'}' ,".
126 "'$self->{'ofv'}' ,".
127 "'$self->{'rounding_errors'}' ,".
128 "'$self->{'s_matrix_singular'}' ,".
129 "'$self->{'significant_digits'}' ,".
130 "'$self->{'simulation'}' ,".
131 "'$self->{'minimization_successful'}' ,".
133 "'$self->{'zero_gradients'}' )");
135 $self -> {'subproblem_id'} = $sth->{'mysql_insertid'};
136 $self -> {'problem_id'} = $problem_id;
137 $self -> {'output_id'} = $output_id;
138 $self -> {'model_id'} = $model_id;
139 foreach my $param ( 'theta', 'omega', 'sigma' ) {
141 foreach my $par_str ( @
{$self -> {$param.'s'}} ) {
142 $sth = $dbh -> prepare
("INSERT INTO ".$PsN::config
-> {'_'} -> {'project'}.
144 "(subproblem_id,problem_id,output_id,".
146 "type,value, number, label) ".
147 "VALUES ( '$self->{'subproblem_id'}' ,".
148 "'$self->{'problem_id'}' ,".
149 "'$self->{'output_id'}' ,".
151 "'$param','$par_str', '$i', 'test_label')");
153 push( @
{$self -> {'estimate_ids'}}, $sth->{'mysql_insertid'} );
161 # if ( $PsN::config -> {'_'} -> {'use_database'} ) {
162 # my $dbh = DBI -> connect("DBI:mysql:host=".$PsN::config -> {'_'} -> {'database_server'}.
163 # ";databse=".$PsN::config -> {'_'} -> {'project'},
164 # $PsN::config -> {'_'} -> {'user'},
165 # $PsN::config -> {'_'} -> {'password'},
166 # {'RaiseError' => 1});
167 # my $sth = $dbh -> prepare( "UPDATE ".$PsN::config -> {'_'} -> {'project'}.
169 # "SET condition_number='".
170 # $self -> {'condition_number'}."'".
171 # "WHERE model_id='".$self -> {'model_id'}."'" );
172 # $sth -> execute or debug -> die( message => $sth->errstr ) ;
174 # $dbh -> disconnect;
176 end register_in_database
178 # }}} register_in_database
180 # {{{ _compute_comegas_or_csigmas
182 start _compute_comegas_or_csigmas
184 # This method transforms omegas or sigmas.
186 # First we check if we have omegas or sigmas.
187 if ( defined $self -> {'raw_' . $omega_or_sigma . 's'} ) {
188 my @raw_omegas_or_sigmas = @
{$self -> {'raw_' . $omega_or_sigma . 's'}};
189 # If the omega or sigma matrix has no off-diagonal elements, the
190 # transformation is quite straightforward.
191 if( $self -> { $omega_or_sigma . '_block_structure_type'} eq 'DIAGONAL' ){
193 # All diagonal omegas or sigmas will be in
194 # @raw_omegas_or_sigmas, so we loop over it and take the square
195 # root of non-negative, non-zero numbers (those become
198 for( my $i = 0; $i <= $#raw_omegas_or_sigmas; $i+=$row_size ){
199 my $omega_or_sigma_value = undef;
200 if( $raw_omegas_or_sigmas[$i] >= 0 ) {
201 $omega_or_sigma_value = sqrt( $raw_omegas_or_sigmas[$i] );
203 ui
-> print( category
=> 'all',
204 message
=> "Warning: cannot take the square root of ".
205 "$omega_or_sigma with value ".$raw_omegas_or_sigmas[$i] );
207 push( @
{$self -> {'c' . $omega_or_sigma .'s'}}, $omega_or_sigma_value );
211 } elsif( $self -> {$omega_or_sigma . '_block_structure_type'} eq 'BLOCK' ) {
213 # If the omega or sigma matrix has block form, the transformation
214 # becomes a bit more complex. The transformation for diagonal
215 # elements is the same. But for off-diagonals it takes more into
218 # $current_row_size is the number of omegas or sigmas in the row
219 # in the matrix that we are currently transforming.
220 my $current_row_size = 1;
222 # $diagonal_index is the index in @raw_omegas_or_sigmas where the current
223 # on-diagonal omega or sigma we are transforming.
224 my $diagonal_index = 0;
226 # $y is the y-coordinate of the element in the matrix we
230 # First get all block sets sorted.
231 my @keys = sort {$a <=> $b} keys( %{$self -> { $omega_or_sigma . '_block_sets'}} );
233 foreach my $key ( @keys ) {
235 # If this is a block set $block_dimension will be > 1
236 # otherwise it will be 1.
237 my $block_dimension = $self -> { $omega_or_sigma . '_block_sets'}{$key}{'dimension'};
238 my $block_size = $self -> { $omega_or_sigma . '_block_sets'}{$key}{'size'};
240 # print "BS: $block_size\n";
241 # print "BD: $block_dimension\n";
243 # loop over the repeated blocks
244 for( my $i = 1; $i <= $block_size; $i++ ) {
245 # loop over the size of the block (i.e. the X in block(X))
246 for( my $j = 1; $j <= $block_dimension; $j++ ) {
249 # The equation y*(y+1)/2 is a geometric sum that gives the
250 # index of the diagonal element on row y in the compacted
251 # matrixarray @raw_omegas_or_sigmas. -1 to get array
253 my $y_y_idx = ($y*($y+1)/2)-1;
255 my $start_x = ($y - $j + 1);
256 for( my $x = $start_x; $x <= $y; $x++ ) {
257 # print "X: $x, Y: $y\n";
258 my $omega_or_sigma_value;
260 # This is the first of the repeated blocks, collect
261 # the values (otherwise, just leave
262 # omega_or_sigma_value undefined)
265 # If we are on the diagonal, just take the square root
266 # of the diagonal element.
267 $omega_or_sigma_value = $raw_omegas_or_sigmas[ $y_y_idx ];
268 $omega_or_sigma_value = sqrt( $omega_or_sigma_value );
269 # print "y_y_idx: $y_y_idx\n";
272 # If we are off the diagonal, we need to find two
273 # on-diagonal omegas, one on the same column and one on
276 my $x_x_idx = ($x*($x+1)/2)-1; # See explanation for $y_y_idx above
278 # Off diagonal index: $y_y_idx for the row before plus $x
279 my $x_y_idx = (($y-1)*$y/2+$x)-1;
281 $omega_or_sigma_value = $raw_omegas_or_sigmas[$x_y_idx];
282 my $denominator = $raw_omegas_or_sigmas[ $x_x_idx ]
283 * $raw_omegas_or_sigmas[ $y_y_idx ];
284 if( $denominator <= 0 ){ # To avoiding division by zero
285 $omega_or_sigma_value = undef;
286 } elsif( $omega_or_sigma_value >= sqrt($denominator) ) {
287 # This rounding handles cases when the offdiagonals
288 # are greater or equal to one.
289 $omega_or_sigma_value = $omega_or_sigma_value/( int( 10000 * sqrt($denominator) )/10000 );
291 $omega_or_sigma_value = $omega_or_sigma_value/sqrt($denominator);
295 push( @
{$self -> {'c' . $omega_or_sigma . 's'}}, $omega_or_sigma_value );
301 # my $loop_limit = $block_dimension > $block_size ? $block_dimension : $block_size;
302 # print "loop limit: $loop_limit\n";
303 # for( my $i = 0; $i < $loop_limit; $i ++ ){
304 # # x_idx is the x-coordinate of the omega or sigma we are
307 # my $x_idx = $y_idx - $i;
308 # # current row size is equal to the y coordinate
309 # # my $x_idx = $current_row_size - $i;
311 # # The innner_loop_limit must be 1 when we have SAME blocks,
312 # # which can be determined from the block_size variable.
313 # my $inner_loop_limit = $block_size > 1 ? 0 : $i;
314 # print "inner loop limit: $inner_loop_limit\n";
315 # # The inner loop is over the row elements in the block
316 # # set. (1 when we have SAME blocks)
317 # for( my $j = 0; $j <= $inner_loop_limit; $j++ ){
319 # # $omega_or_sigma will hold the transformed value.
320 # my $omega_or_sigma_value;
322 # print "X: $x_idx, Y: $y_idx\n";
323 # if( $x_idx == $y_idx ) {
325 # # If we are on the diagonal, just take the square root
326 # # of the diagonal element.
327 # $omega_or_sigma_value = $raw_omegas_or_sigmas[ $diagonal_index ];
328 # $omega_or_sigma_value = sqrt( $omega_or_sigma_value );
331 # # If we are off the diagonal, we need to find two
332 # # on-diagonal omegas, one on the same column and one on
335 # # The equation y*(y+1)/2 is a geometric sum that gives
336 # # the index of the diagonal element on row y in the
337 # # compacted matrixarray @raw_omegas_or_sigmas. The equation
338 # # x*(x+1)/2 gives the diagonal element on column x in
341 # # We find the omega by finding the index of the diagonal
342 # # element on row y and subtracting the difference
343 # # between the number of elements on the row ($i) and the
344 # # number of elements we have transformed ($j).
346 # $omega_or_sigma_value = $raw_omegas_or_sigmas[(($y_idx*($y_idx+1))/2)-1 - ($i - $j)];
347 # my $denominator = $raw_omegas_or_sigmas[ (($x_idx*($x_idx+1))/2)-1 ]
349 # $raw_omegas_or_sigmas[ (($y_idx*($y_idx+1))/2)-1 ];
350 # if( $denominator <= 0 ){ # To avoiding division by zero
351 # $omega_or_sigma_value = undef;
352 # } elsif( $omega_or_sigma_value >= sqrt($denominator) ) {
353 # # This rounding handles cases when the offdiagonals
354 # # are greater or equal to one.
355 # $omega_or_sigma_value = $omega_or_sigma_value/( int( 10000 * sqrt($denominator) )/10000 )
357 # $omega_or_sigma_value = $omega_or_sigma_value/sqrt($denominator);
360 # push( @{$self -> {'c' . $omega_or_sigma . 's'}}, $omega_or_sigma_value );
362 # # Move the x-coordinate forwards.
366 # # Move the y-coordinate forwards.
368 # # Calculate the new row size.
369 # # $current_row_size ++;
370 # # Skip one row and we get the index of the next diagonal.
372 # $diagonal_index += $y_idx;
373 # # $diagonal_index += $current_row_size;
377 'debug' -> warn( level
=> 1,
378 message
=> $omega_or_sigma . ' matrix has unknown form.' );
382 end _compute_comegas_or_csigmas
384 # }}} _compute_comegas_or_sigmas
386 # {{{ _compute_comegas
387 start _compute_comegas
389 $self -> _compute_comegas_or_csigmas
( omega_or_sigma
=> 'omega' );
393 # This is the old algoritm for transforming omegas. It can't handle
394 # of-diagonals omegas that are zero, if that should ever happen.
398 # my @computed_omegas;
402 # @raw_omegas = @{$self -> {'raw_omegas'}};
403 # @computed_omegas = ();
405 # if( $self -> {'omega_structure_type'} eq 'DIAGONAL' ){
406 # @diags = @raw_omegas;
408 # ## Collect the diagonals
409 # foreach $i (0..$#raw_omegas) {
410 # if( $self -> _isdiagonal('index' => $i+1) ){
411 # push( @diags, $raw_omegas[$i] );
416 # foreach $i (0..$#raw_omegas){
417 # if($self -> _isdiagonal('index' => $i+1)) {
418 # if( $raw_omegas[$i] <= 0 ){
419 # push( @computed_omegas, $raw_omegas[$i] );
422 # push @computed_omegas, sqrt($raw_omegas[$i]);
425 # @indices = $self -> _rowcolind( index => $i+1 );
426 # if( ($raw_omegas[$i] == 0) or ($diags[$indices[0]-1]*$diags[$indices[1]-1]) <= 0 ) {
429 # push @computed_omegas,
430 # $raw_omegas[$i]/sqrt($diags[$indices[0]-1]*$diags[$indices[1]-1]);
434 # $self -> {'comegas'}= \@computed_omegas;}
438 # {{{ _compute_csigmas
439 start _compute_csigmas
441 $self -> _compute_comegas_or_csigmas
( omega_or_sigma
=> 'sigma' );
444 # This is the old algoritm for transforming sigmass. It can't handle
445 # of-diagonals sigmass that are zero, if that should ever happen.
448 # if (defined $self -> {'raw_sigmas'} ) {
450 # my ( @om, @com, @diags, @indices );
451 # @om = @{$self -> {'raw_sigmas'}};
453 # ## Collect the diagonals
454 # foreach $i (0..$#om) {
455 # push @diags,$om[$i] if $self -> _isdiagonal('index' => $i+1);
457 # foreach $i (0..$#om){
458 # if($self -> _isdiagonal('index' => $i+1)) {
459 # if( $om[$i] <= 0 ){
462 # push @com, sqrt($om[$i]);
465 # @indices = $self -> _rowcolind( index => $i+1 );
466 # if( ($om[$i] == 0) or ($diags[$indices[0]-1]*$diags[$indices[1]-1] <= 0) ) {
470 # $om[$i]/sqrt($diags[$indices[0]-1]*$diags[$indices[1]-1]);
474 # $self -> {'csigmas'}= \@com;
478 # }}} _compute_csigmas
480 # {{{ _compute_cvseomega
482 start _compute_cvseomega
484 if( defined $self -> raw_omegas
() and defined $self -> raw_seomegas
() ) {
485 my @raw_omegas = @
{$self -> raw_omegas
()};
486 my @raw_seomegas = @
{$self -> raw_seomegas
()};
489 if ( scalar @raw_seomegas > 0) {
491 my ( @init_om, @init_seom );
493 foreach $i (0.. $#raw_seomegas){
494 if( $self -> _isdiagonal
('index' => $i+1)) {
495 push @init_seom, $raw_seomegas[$i];
498 if(($raw_seomegas[$i] eq 'NA') or ($raw_seomegas[$i] == 0)) {
501 push @init_seom, $raw_seomegas[$i];
506 foreach $i (0..$#raw_omegas){
507 if( $self -> _isdiagonal
('index' => $i+1)) {
508 push @init_om, $raw_omegas[$i];
511 if($raw_omegas[$i] == 0) {
514 push @init_om, $raw_omegas[$i];
519 foreach my $i (0..$#init_om) {
520 if( $init_seom[$i] ne 'NA' and $init_om[$i] ne 'NA' ){
521 if( ($init_seom[$i] == 'INF' or $init_seom[$i] == '-INF') and
522 ($init_om[$i] == 'INF' or $init_om[$i] == '-INF') ) {
523 push @cvseomega,undef;
524 } elsif ( $init_seom[$i] == 'INF' ) {
525 push @cvseomega,'INF';
526 } elsif ( $init_seom[$i] == '-INF' ) {
527 push @cvseomega,'-INF';
528 } elsif ( $init_om[$i] == 'INF' or
529 $init_om[$i] == '-INF' ) {
532 push @cvseomega,$init_seom[$i]/abs($init_om[$i]);
535 push @cvseomega,undef;
537 # push @cvseomega,$init_seom[$i]/$init_om[$i]
538 # if ($init_seom[$i] && $init_om[$i]);
539 # push @cvseomega,"NA" unless ($init_seom[$i] && $init_om[$i]);
544 $self -> cvseomegas
([@cvseomega]);
547 end _compute_cvseomega
549 # }}} _compute_cvseomega
551 # {{{ _compute_cvsesigma
552 start _compute_cvsesigma
554 if( defined $self -> raw_sigmas
() and defined $self -> raw_sesigmas
() ) {
555 my @raw_sigmas = @
{$self -> raw_sigmas
()};
556 my @raw_sesigmas = @
{$self -> raw_sesigmas
()};
559 if ( scalar @raw_sesigmas > 0) {
561 my ( @init_si, @init_sesi );
563 foreach $i (0.. $#raw_sesigmas){
564 if($self -> _isdiagonal
('index' => $i+1)) {
565 push @init_sesi, $raw_sesigmas[$i];
568 if(($raw_sesigmas[$i] eq 'NA') or ($raw_sesigmas[$i] == 0)) {
571 push @init_sesi, $raw_sesigmas[$i];
576 foreach $i (0.. $#raw_sigmas){
577 if($self -> _isdiagonal
('index' => $i+1)) {
578 push @init_si, $raw_sigmas[$i];
581 if($raw_sigmas[$i] == 0) {
584 push @init_si, $raw_sigmas[$i];
589 foreach my $i (0..$#init_si) {
590 if( $init_sesi[$i] ne 'NA' and $init_si[$i] ne 'NA' ){
591 if( ($init_sesi[$i] == 'INF' or $init_sesi[$i] == '-INF') and
592 ($init_si[$i] == 'INF' or $init_si[$i] == '-INF') ) {
593 push @cvsesigma,undef;
594 } elsif ( $init_sesi[$i] == 'INF' ) {
595 push @cvsesigma,'INF';
596 } elsif ( $init_sesi[$i] == '-INF' ) {
597 push @cvsesigma,'-INF';
598 } elsif ( $init_si[$i] == 'INF' ) {
601 push @cvsesigma,$init_sesi[$i]/abs($init_si[$i]);
604 push @cvsesigma,undef;
610 $self -> cvsesigmas
([@cvsesigma]);
613 end _compute_cvsesigma
614 # }}} _compute_cvsesigma
616 # {{{ _compute_cvsetheta
617 start _compute_cvsetheta
619 if( defined $self -> thetas
() and defined $self -> sethetas
() ) {
620 my @thetas = @
{$self -> thetas
()};
621 my @sethetas = @
{$self -> sethetas
()};
624 if ( scalar @sethetas > 0 ) {
625 foreach my $i (0..$#thetas) {
626 if( defined $sethetas[$i] and
627 defined $thetas[$i] ) {
628 if( $thetas[$i] != 0 ) {
629 push(@cvsethetas,$sethetas[$i]/abs($thetas[$i]));
630 } elsif( $sethetas[$i] > 0 ) {
631 push(@cvsethetas,'INF');
633 push(@cvsethetas,'-INF');
636 push @cvsethetas,"NA";
641 $self -> cvsethetas
([@cvsethetas]);
644 end _compute_cvsetheta
645 # }}} _compute_cvsetheta
652 return(1) if $index == 1;
653 foreach my $j (2..100) {
654 return(1) if $index == $previ+$j;
656 last if $index < $previ;
662 # {{{ _read_matrixoestimates
663 start _read_matrixoestimates
665 # Reads one matrix structure and returns the file handle at
666 # the beginning of the next structure
667 while ( $_ = @
{$self -> {'lstfile'}}[ $pos++ ] ) {
669 # Rewind one step if we find something that marks the end of
671 $pos-- and last if ( /^ PROBLEM.*SUBPROBLEM/ or /^ PROBLEM NO\.:\s+\d/ );
672 $pos-- and last if (/^[a-df-zA-DF-Z]/);
674 next if ( /^\s+TH/ or /^\s+OM/ or /^\s+SG/ ); # Header row
675 next if ( /^1/ ); # Those annoying 1's
677 chomp; # Get rid of line-feed
679 shift( @row ) if ( $row[0] eq '+' ); # Get rid of +-sign
681 next if ( $#row < 0 ); # Blank row
683 push( @subprob_matrix, @row );
685 $success = 1 if( scalar @subprob_matrix > 0 );
687 end _read_matrixoestimates
688 # }}} _read_matrixoestimates
690 # {{{ _read_covmatrix
691 start _read_covmatrix
694 my ( $t_success, $c_success, $corr_success, $i_success ) = (0,0,0,0);
695 my $start_pos = $self -> {'lstfile_pos'}-1;
701 my @matrix = @
{$m_ref};
702 # get rid of '........'
704 foreach ( @matrix ) {
705 unless ( $_ eq '.........' ) {
708 } elsif ( $_ eq 'INF' ) {
709 push( @clear, 99999999999999 );
710 } elsif ( $_ eq '-INF' ) {
711 push( @clear, -99999999999999 );
722 # {{{ sub make square
726 my @matrix = @
{$m_ref};
727 # Make the matrix square:
728 my $elements = scalar @matrix; # = M*(M+1)/2
729 my $M = -0.5 + sqrt( 0.25 + 2 * $elements );
731 for ( my $m = 1; $m <= $M; $m++ ) {
732 for ( my $n = 1; $n <= $m; $n++ ) {
733 push( @
{$square[$m-1]}, $matrix[($m-1)*$m/2 + $n - 1] );
734 unless ( $m == $n ) {
735 push( @
{$square[$n-1]}, $matrix[($m-1)*$m/2 + $n - 1] );
744 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
746 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
747 if (/^ TH (\d)/ or /^\s+TH (\d) \| /) { # Read matrix and get out of inner while loop
748 ( $start_pos, $self -> {'raw_tmatrix'}, $t_success ) = $self ->
749 _read_matrixoestimates
( pos => $start_pos ) and last;
752 last; # No covariance matrix will be found!
754 if (/ COVARIANCE MATRIX OF ESTIMATE/) {
755 while( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
756 if (/^ TH (\d)/ or /^\s+TH (\d) \| /) { # Read matrix and get out of inner while loop
757 ( $start_pos, $self -> {'raw_covmatrix'}, $c_success ) = $self ->
758 _read_matrixoestimates
( pos => $start_pos ) and last;
762 if (/ CORRELATION MATRIX OF ESTIMATE/) {
763 while( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
764 if (/^ TH (\d)/ or /^\s+TH (\d) \| /) { # Read matrix and get out of inner while loop
765 ( $start_pos, $self -> {'raw_cormatrix'}, $corr_success ) = $self ->
766 _read_matrixoestimates
( pos => $start_pos ) and last;
770 if (/ INVERSE COVARIANCE MATRIX OF ESTIMATE/) {
771 while( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
772 if (/^ TH (\d)/ or /^\s+TH (\d) \| /) { # Read matrix and get out of inner while loop
773 ( $start_pos, $self -> {'raw_invcovmatrix'}, $i_success ) = $self ->
774 _read_matrixoestimates
( pos => $start_pos ) and last;
780 foreach my $element ( @
{$self -> {'raw_tmatrix'}} ) {
781 push( @
{$self -> {'t_matrix'}}, eval($element) ) unless ( $element eq '.........' );
783 foreach my $element ( @
{$self -> {'raw_covmatrix'}} ) {
784 push( @
{$self -> {'covariance_matrix'}}, eval($element) ) unless ( $element eq '.........' );
786 foreach my $element ( @
{$self -> {'raw_cormatrix'}} ) {
787 push( @
{$self -> {'correlation_matrix'}}, eval($element) ) unless ( $element eq '.........' );
790 if( defined $self -> {'raw_invcovmatrix'} ) {
791 $self -> {'inverse_covariance_matrix'} = Math
::MatrixReal
->
792 new_from_cols
( make_square
( clear_dots
( $self -> {'raw_invcovmatrix'} ) ) );
795 # foreach my $element ( @{$self -> {'raw_invcovmatrix'}} ) {
796 # push( @{$self -> {'inverse_covariance_matrix'}}, eval($element) ) unless ( $element eq '.........' );
799 #If something has gone right!
800 $self-> {'lstfile_pos'} = $start_pos if ( $t_success + $c_success + $corr_success + $i_success );
803 # }}} _read_covmatrix
810 my $start_pos = $self -> {'lstfile_pos'};
812 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
814 if ( /EIGENVALUES OF COR MATRIX OF ESTIMATE/ ) {
816 $start_pos = $start_pos + 4 ; # Jump forward to the index numbers
817 debug
-> warn( level
=> 2,
818 message
=> "Found the eigenvalue area" );
819 INNER
: while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) { # Get rid of indexes
820 last INNER
if ( not /^\s+\d/ );
821 # $start_pos++ and last INNER if ( not /^\s+\d/ );
825 $start_pos-- and last if (/^[a-df-zA-DF-Z]/); #Rewind one step
826 last if ( /^\s*\*/ or /^1/ );
827 push( @eigens, split );
829 $start_pos-- and last if ( /^ PROBLEM.*SUBPROBLEM/ or /^ PROBLEM NO\.:\s+\d/ );
830 $start_pos-- and last if (/^[a-df-zA-DF-Z]/); #Rewind one step
832 if ( scalar @eigens > 0 ) {
833 my @list = sort { $a <=> $b } @eigens;
834 $self -> {'condition_number'} = abs($list[$#list]/$list[0]) if ( $list[0] != 0 );
836 @
{$self -> {'eigens'}} = @eigens;
845 my $start_pos = $self -> {'lstfile_pos'};
847 while( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) {
848 if ( / PROBLEM NO\.:\s*\d+\n/ ) {
849 $self -> parsing_error
( message
=> "Error in reading the number of ".
850 "function evaluations!\nNext problem found" );
854 if ( $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
855 $self -> parsing_error
( message
=> "Error in reading number of ".
856 "function evaluations!\nEOF found\n" );
860 if ( /^1/ or /MINIMUM VALUE OF OBJECTIVE FUNCTION/ ) {
861 $self -> parsing_error
( message
=> "Error in reading number of ".
862 "function evaluations!\nOFV found" );
866 if ( / NO. OF FUNCTION EVALUATIONS USED:\s*(\d*)/ ){
875 # {{{ _read_iteration_path
876 start _read_iteration_path
878 my $start_pos = $self -> {'lstfile_pos'};
880 my (@func_eval, @parameter_vectors,
881 @gradient_vectors) = ((), (), (), (), ());
882 my @numsigdig_vectors;
883 my $cumulative_evals = 0;
884 my $zero_gradients = 0;
885 my $hessian_reset = 0;
886 my $found_monitoring = 0;
887 while ( $_ = @
{$self -> {'lstfile'}}[ $start_pos++ ] ) { #Large reading loop
888 if ( /MONITORING OF SEARCH/ ) {
889 $found_monitoring = 1;
892 if ( $found_monitoring and
893 $start_pos >= scalar @
{$self -> {'lstfile'}} ) {
894 # This is probably (we cannot be really sure but it is
895 # likely) a "NONMEM black hole"-situation. We stop parsing
896 # but do not indicate that we had problems parsing the
898 $self -> parsing_error_message
("Found \" MONITORING OF SEARCH:\" but no".
899 " records of the iterations before the end".
900 " of the output file. This is a sign of a".
901 " \"NONMEM black hole\"-situation. We cannot ".
902 "be 100% sure of this based on this type of".
903 " output so please take a good look at the files\n");
904 $self -> parsed_successfully
(1);
905 $self -> finished_parsing
(1);
909 if ( /0PROGRAM TERMINATED BY OBJ/ ) {
910 # This is an error message which terminates NONMEM. We
911 # return after reading the minimization message
912 $self -> minimization_successful
(0);
913 $self -> _read_minimization_message
();
914 $self -> finished_parsing
(1);
918 if (/^0ITERATION NO/) {
919 unless (/0ITERATION NO\.:\s+(\d+)\s+OBJECTIVE VALUE:\s+(\S+)\s+NO\. OF FUNC\. EVALS\.:\s*(.+)/) {
920 debug
-> warn( level
=> 1,
921 message
=> "Error in reading iteration path!\n$!" );
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 );
1606 if (s/\s+ETABAR:\s+//) {
1608 push @etabar, @temp;
1609 # print "Etabar Push of: $_ \n";
1610 for (@mess) { #If wrapped etabar-lines
1612 last if(/a-zA-DF-Z/);
1613 last unless (s/^\s+//);
1616 push @etabar, @temp;
1621 # Initialize the attribute only if we have found any data
1622 $self -> {'etabar'} = \
@etabar if ( $#etabar > 0 );
1626 if (s/\s+P VAL\.:\s+//) {
1629 # print "Pval Push of: $_ \n";
1630 for (@mess) { #If wrapped etabar-lines
1632 last if(/a-zA-DF-Z/);
1633 last unless (s/^\s+//);
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