1 # 2004-12-08: FCON must be adjusted for multiple problems /Lasse
3 start include statements
4 # A Perl module for parsing and manipulating NONMEM FCON files
12 my $items_collected = 0;
13 while( $items_collected < $nr_items ){
14 my $items_per_line = ($nr_items - $items_collected) < (72 / $tabSize) ? ($nr_items - $items_collected): (72 / $tabSize);
16 my $line = $fcon[$index++];
21 for( ; $items_per_line > 0; $items_per_line -- ){
22 $line =~ s/^(.{$tabSize})//;
24 unless( $val =~ /[\ ]{8}/ ){ # Check for blanks
25 $val = $val * 1; # Cheeky trick to make $val a number instead of a string
31 push(@values, $index-1);
39 while( not $fcon[$index+1] =~ /^[A-Z]{4}[\ ]{3}/ ){
41 if( $index > $#fcon ){
53 for( my $i = $batchStart; $i < $batchStart+$batchSize; $i++ ){
54 for( my $try = 0; $try < $retries[$i - $batchStart]; $try++ ){
55 system( "./NM_run".($i+1) . '_nonmem.sh' ) == 0 or die "Unable to execute NM_run".($i+1) . "_nonmem.sh $!\n";
56 open( my $outfile, "<NM_run".($i+1) . '_psn.lst' );
59 if((/^0MINIMIZATION TERMINATED/ or /^0PROGRAM TERMINATED/) # If hard termination
60 or # We are picky and check some softer rerun requirements
61 ($picky[$i - $batchStart] and
62 (/0ESTIMATE OF THETA IS NEAR THE BOUNDARY AND/ or
63 /0PARAMETER ESTIMATE IS NEAR ITS BOUNDARY/ or
64 /0R MATRIX ALGORITHMICALLY SINGULAR/ or
65 /0S MATRIX ALGORITHMICALLY SINGULAR/
69 print "NONMEM failed. Preparing rerun number" . $try+1 . " / " . $retries[$i - $batchStart] . "\n";
72 $self -> {'filename'} = "NM_run".($i+1) . '_FCON';
73 $self -> parse
('filename' => "NM_run".($i+1) . '_FCON' );
74 $self -> pertubate_all
('fixed_thetas' => $fixed_thetas[$i],
75 'fixed_omegas' => $fixed_omegas[$i],
76 'fixed_sigmas' => $fixed_omegas[$i]);
77 $self -> write('filename' => "NM_run".($i+1) . '_FCON' );
95 $self -> {'fcon_lines'} = undef;
96 $self -> {'theta_values'} = undef;
97 $self -> {'have_omega_DIAG'} = undef;
98 $self -> {'omega_values'} = undef;
99 $self -> {'have_sigma_DIAG'} = undef;
100 $self -> {'have_omega_BLST'} = undef;
101 $self -> {'have_sigma_BLST'} = undef;
111 open($fcon,"<",$self -> {'filename'}) or die "fcon_file: Unable to open ", $self -> {'filename'}, " : $!";
112 my @fcon_lines = <$fcon>;
113 $self -> fcon_lines
( \
@fcon_lines );
120 my @have_initial_STRC;
125 my @expect_sigma_BLST;
126 my @expect_omega_BLST;
130 my @sigma_BLST_lengths;
131 my @omega_BLST_lengths;
133 my @expect_sigma_DIAG;
134 my @expect_omega_DIAG;
142 for( my $i = 0; $i <= $#fcon_lines; $i++ ){
143 my $line = $fcon_lines[$i];
144 if( $line =~ /^FILE/ ){
145 #print "$i " . $line;
146 }elsif( $line =~ /^PROB/ ){
148 $self -> prob
($prob);
149 #print "$i " . $line;
150 }elsif ( $line =~ /^DATA/ ){
152 }elsif ( $line =~ /^ITEM/ ){
154 }elsif ( $line =~ /^INDX/ ){
156 $i = $self -> _skip_lines
( 'fcon' => \
@fcon_lines,
158 }elsif ( $line =~ /^LABL/ ){
160 $i = $self -> _skip_lines
( 'fcon' => \
@fcon_lines,
162 }elsif ( $line =~ /^FORM/ ){
164 $i = $self -> _skip_lines
( 'fcon' => \
@fcon_lines,
166 }elsif ( $line =~ /^FIND/ ){
168 $i = $self -> _skip_lines
( 'fcon' => \
@fcon_lines,
170 $have_FIND[$prob] = 1;
171 }elsif ( $line =~ /^STRC/ ){
173 if( $have_FIND[$prob] ){
174 die "Malformated FCON (STRC unexpectedly found)\n";
177 my @values = @
{$self -> _get_array
( 'fcon' => \
@fcon_lines,
183 unless( $have_initial_STRC[$prob] ){
184 $have_initial_STRC[$prob] = 1;
185 $nr_thetas[$prob] = $values[0];
186 #$expect_bounds = $values[3];
187 $expect_omega_DIAG[$prob] = $values[1];
188 $expect_sigma_DIAG[$prob] = $values[2];
189 $expect_omega_BLST[$prob] = $values[5] ?
0 : $values[6];
190 $expect_sigma_BLST[$prob] = $values[7] ?
0 : $values[8];
192 unless( $have_omega_STRC[$prob] ){
193 if( $expect_omega_BLST[$prob] ){
194 @omega_BLST_lengths[$prob] = @values;
196 $have_omega_STRC[$prob] = 1;
198 if( $expect_sigma_BLST[$prob] ){
199 @sigma_BLST_lengths[$prob] = @values;
201 $have_sigma_STRC[$prob] = 1;
205 }elsif ( $line =~ /^THTA/ ){
207 if( $have_initial_STRC[$prob] ){
208 my @values = @
{$self -> _get_array
( 'fcon' => \
@fcon_lines,
211 'nr_items' => $nr_thetas[$prob] )};
213 $self -> {'theta_values'} = [] unless defined $self -> {'theta_values'};
214 $self -> theta_values
-> [$prob] = \
@values;
216 die "Malformated FCON (THTA unexpectedly found)\n";
219 }elsif ( $line =~ /^LOWR/ ){
221 #if( $expect_bounds ){
222 my @values = @
{$self -> _get_array
( 'fcon' => \
@fcon_lines,
225 'nr_items' => $nr_thetas[$prob] )};
227 $self -> {'lower_bounds'} = [] unless defined $self -> {'lower_bounds'};
228 $self -> lower_bounds
-> [$prob] = \
@values;
229 #} else { ## I'd like to uncomment this.. but most FCONs seams malformated in this way. And its easy to ignore
230 #die "Malformated FCON (LOWR unexpectedly found)\n";
232 }elsif ( $line =~ /^UPPR/ ){
234 #if( $expect_bounds ){
235 my @values = @
{$self -> _get_array
( 'fcon' => \
@fcon_lines,
238 'nr_items' => $nr_thetas[$prob] )};
240 $self -> {'upper_bounds'} = [] unless defined $self -> {'upper_bounds'};
241 $self -> upper_bounds
-> [$prob] = \
@values;
242 #} else { ## I'd like to uncomment this.. but most FCONs seams malformated in this way. And its easy to ignore
243 #die "Malformated FCON (UPPR unexpectedly found)\n";
245 }elsif ( $line =~ /^DIAG/ ){
247 if( $expect_omega_DIAG[$prob] and not $have_omega_DIAG[$prob] and not ($expect_omega_BLST[$prob] or $have_omega_BLST[$prob]) ){
248 my @values = @
{$self -> _get_array
( 'fcon' => \
@fcon_lines,
251 'nr_items' => $expect_omega_DIAG[$prob] )};
253 $self -> {'omega_values'} = [] unless defined $self -> {'omega_values'};
254 $self -> omega_values
-> [$prob] -> [0] = \
@values;
255 $have_omega_DIAG[$prob] = 1;
256 $self -> {'have_omega_DIAG'} = [] unless defined $self -> {'have_omega_DIAG'};
257 $self -> have_omega_DIAG
-> [$prob] = 1;
258 } elsif( $expect_sigma_DIAG[$prob] and not $have_sigma_DIAG[$prob] and not ($expect_sigma_BLST[$prob] or $have_sigma_BLST[$prob]) ) {
259 my @values = @
{$self -> _get_array
( 'fcon' => \
@fcon_lines,
262 'nr_items' => $expect_sigma_DIAG[$prob] )};
264 $self -> {'sigma_values'} = [] unless defined $self -> {'sigma_values'};
265 $self -> sigma_values
-> [$prob] -> [0] = \
@values;
266 $have_sigma_DIAG[$prob] = 1;
267 $self -> {'have_sigma_DIAG'} = [] unless defined $self -> {'have_sigma_DIAG'};
268 $self -> have_sigma_DIAG
-> [$prob] = 1;
270 }elsif ( $line =~ /^BLST/ ){
272 if( $expect_sigma_BLST[$prob] or $expect_omega_BLST[$prob] ){
273 if( $expect_omega_BLST[$prob] ){
274 $expect_omega_BLST[$prob] --;
276 my @values = @
{$self -> _get_array
( 'fcon' => \
@fcon_lines,
281 $self -> omega_values
-> [$prob] -> [$have_omega_BLST[$prob]] = \
@values;
283 $have_omega_BLST[$prob]++;
284 $self -> {'have_omega_BLST'} = [] unless defined $self -> {'have_omega_BLST'};
285 $self -> have_omega_BLST
-> [$prob] = 1;
286 } elsif( $expect_sigma_BLST[$prob] ){
287 $expect_sigma_BLST[$prob] --;
289 my @values = @
{$self -> _get_array
( 'fcon' => \
@fcon_lines,
295 $self -> sigma_values
-> [$prob] -> [$have_sigma_BLST[$prob]] = \
@values;
297 $have_sigma_BLST[$prob]++;
298 $self -> {'have_sigma_BLST'} = [] unless defined $self -> {'have_sigma_BLST'};
299 $self -> have_sigma_BLST
-> [$prob] = 1;
302 die "Malformated FCON (DIAG unexpectedly found)\n";
304 }elsif ( $line =~ /^ESTM/ ){
306 $i = $self -> _skip_lines
( 'fcon' => \
@fcon_lines,
308 }elsif ( $line =~ /^COVR/ ){
310 $i = $self -> _skip_lines
( 'fcon' => \
@fcon_lines,
312 }elsif ( $line =~ /^TABL/ ){
314 $i = $self -> _skip_lines
( 'fcon' => \
@fcon_lines,
316 }elsif ( $line =~ /^SCAT/ ){
318 $i = $self -> _skip_lines
( 'fcon' => \
@fcon_lines,
321 print "Found something new: \n $line \n" if $self -> debug
;
322 $i = $self -> _skip_lines
( 'fcon' => \
@fcon_lines,
336 my @omega_BLST_count;
337 my @sigma_BLST_count;
341 open( my $outfile, ">". $filename ) or die "fcon_file: Unable to open FCON file: $!";
343 foreach my $line (@
{$self -> fcon_lines
}){
344 if( $line =~ /^PROB/ ){
346 print $outfile $line;
347 } elsif ( $line =~ /^(THTA.{4})/ ){
351 foreach my $theta ( @
{$self -> theta_values
-> [$prob]} ){
352 print $outfile "\n " unless( $i % 10 );
354 printf $outfile ("%8s",$theta);
357 } elsif ( $line =~ /^(DIAG.{4})/ ){
362 if( $self -> have_omega_DIAG
-> [$prob] && !$have_omega_DIAG[$prob] ){
363 @diag = @
{$self -> omega_values
-> [$prob] -> [0]};
364 $have_omega_DIAG[$prob] = 1;
365 } elsif ( $self -> have_sigma_DIAG
-> [$prob]) {
366 @diag = @
{$self -> sigma_values
-> [$prob] -> [0]};
368 foreach my $diag ( @diag ){
369 print $outfile "\n " unless( $i % 10 );
371 printf $outfile ("%8s",$diag);
374 } elsif ( $line =~ /^(BLST.{4})/ ) {
379 if( $self -> have_omega_BLST
-> [$prob] && $omega_BLST_count[$prob] <= $#{$self -> omega_values -> [$prob]} ){
380 @blst = @
{$self -> omega_values
-> [$prob] -> [$omega_BLST_count[$prob]++]};
382 @blst = @
{$self -> sigma_values
-> [$prob] -> [0]};
385 foreach my $blst ( @blst ){
386 print $outfile "\n " unless( $i % 10 );
388 printf $outfile ("%8s",$blst);
391 } elsif( not $line =~ /^[A-Z]{4}[\ ]{3}/ and $skip_line){
395 print $outfile $line;
406 for( my $i = 0; $i <= $self -> prob
; $i++ ){
407 $self -> _pertubate
( 'estimates' => $self -> theta_values
-> [$i],
409 'lobnds' => $self -> lower_bounds
-> [$i],
410 'upbnds' => $self -> upper_bounds
-> [$i],
411 'fixed' => $fixed_thetas[$i]);
413 foreach my $sigma_line ( @
{$self -> sigma_values
-> [$i]} ){
414 $self -> _pertubate
( 'estimates' => $sigma_line,
416 'fixed' => $fixed_sigmas[$i]);
419 foreach my $omega_line ( @
{$self -> omega_values
-> [$i]} ){
420 $self -> _pertubate
( 'estimates' => $omega_line,
422 'fixed' => $fixed_omegas[$i]);
433 for( my $i = 0; $i <= $#{$estimates}; $i++ ){
434 unless( $fixed[$i] ){
435 my ( $sign, $est, $form );
438 my $init = $estimates -> [$i];
440 my $change = abs($degree*$init);
442 if ( defined $lobnds and defined $lobnds -> [$i] ){
443 $lobnd = $lobnds -> [$i];
444 $lobnd = $init-$change < $lobnd ?
$lobnd : $init-$change;
446 $lobnd = $init-$change;
449 if ( defined $upbnds and defined $upbnds -> [$i] ) {
450 $upbnd = $upbnds -> [$i];
451 $upbnd = $init+$change > $upbnd ?
$upbnd : $init+$change;
453 $upbnd = $init+$change;
456 $lobnd = 0.01 if ( ( $lobnd < 0.01 and $lobnd > -0.01)
457 and $upbnd >= 0.01001 );
458 $upbnd = -0.01 if ( ( $upbnd < 0.01 and $upbnd > -0.01)
459 and $lobnd <= -0.01001 );
462 if ( $lobnd <= -0.01 and $upbnd >= 0.01 ) {
463 $est = $lobnd + 0.02 + rand($upbnd - ($lobnd+0.02));
464 #$est = random_uniform(1, $lobnd + 0.02, $upbnd);
465 $est = $est - 0.02 if ( $est <0.01 );
467 $est = $lobnd + rand($upbnd - $lobnd);
468 #$est = random_uniform(1, $lobnd, $upbnd );
470 $form = "%6.4f" if $est < 1000 and $est > -999;
471 $form = "%6.1f" if $est >= 1000 or $est <=-999;
474 $estimates -> [$i] = sprintf $form,$est;
475 if ( $estimates -> [$i] == 0 ) {
476 $estimates -> [$i] = '0.0001';