1 # TODO: All: 2004-09-06 Fix absolute paths for data and output files. (under both
6 start include statements
7 use Digest
::MD5
'md5_hex';
14 use POSIX
qw(ceil floor);
15 use model
::shrinkage_module
;
16 end include statements
18 # }}} include statements
20 # {{{ description, synopsis and see_also
22 # No method, just documentation
27 PsN::model is a Perl module for parsing and manipulating NONMEM model
30 The model class is built around the NONMEM model file. This is an
31 ordinary ASCII text file that, except for the data, holds all
32 information needed for fitting a non-linear mixed effect model using
33 NONMEM. Typically, a model file contains specifications for a
34 pharmacokinetic and/or a pharmacodynamic model, initial estimates of
35 model parameters, boundaries for model parameters as well as details
36 about the data location and format.
48 C<< my $model_object = model -> new ( filename => 'pheno.mod' ); >>
56 $model_object -> initial_values ( parameter_type => 'theta',
57 parameter_numbers => [[1,3]],
58 new_values => [[1.2,34]] );
76 <a HREF="data.html">data</a>, <a HREF="output.html">output</a>
104 $model = model -> new( filename => 'run1.mod' )
108 This is the simplest and most common way to create a model
109 object and it requires a file on disk.
113 $model = model -> new( filename => 'run1.mod',
118 If the target parameter is set to anything other than I<mem>
119 the output object (with file name given by the model
120 attribute I<outputfile>) and the data objects (identified by
121 the data file names in the $DATA NONMEM model file section)
122 will be initialized but will contain no information from
123 their files. If information from them are requiered later
124 on, they are read and parsed and the appropriate attributes
125 of the data and output objects are set.
132 if ( defined $parm{'problems'} ) {
133 $this -> {'problems'} = $parm{'problems'};
135 ($this -> {'directory'}, $this -> {'filename'}) =
136 OSspecific
::absolute_path
( $this -> {'directory'}, $this -> {'filename'} );
137 $this -> _read_problems
;
138 $this -> {'synced'} = 1;
141 if ( defined $parm{'active_problems'} ) {
142 $this -> {'active_problems'} = $parm{'active_problems'};
143 } elsif ( defined $this -> {'problems'} ) {
145 for ( @
{$this -> {'problems'}} ) {
148 $this -> {'active_problems'} = \
@active;
151 if ( defined $this -> {'extra_data_files'} ){
152 for( my $i; $i < scalar @
{$this -> {'extra_data_files'}}; $i++ ){
153 my ( $dir, $file ) = OSspecific
::absolute_path
( $this -> {'directory'}, $this -> {'extra_data_files'} -> [$i]);
154 $this -> {'extra_data_files'} -> [$i] = $dir . $file;
158 my $subroutine_files = $this -> subroutine_files
;
159 if( defined $subroutine_files and scalar @
{$subroutine_files} > 0 ){
160 push( @
{$this -> {'extra_files'}}, @
{$subroutine_files} );
163 if ( defined $this -> {'extra_files'} ){
164 for( my $i; $i < scalar @
{$this -> {'extra_files'}}; $i++ ){
165 my ( $dir, $file ) = OSspecific
::absolute_path
( $this -> {'directory'}, $this -> {'extra_files'} -> [$i]);
166 $this -> {'extra_files'} -> [$i] = $dir . $file;
170 # Read datafiles, if any.
171 unless( defined $this -> {'datas'} and not $this -> {'quick_reload'} ){
172 my @idcolumns = @
{$this -> idcolumns
};
173 my @datafiles = @
{$this -> datafiles
('absolute_path' => 1)};
174 # my @datafiles = @{$this -> datafiles('absolute_path' => 0)};
175 for ( my $i = 0; $i <= $#datafiles; $i++ ) {
176 my $datafile = $datafiles[$i];
177 my $idcolumn = $idcolumns[$i];
178 my ( $cont_column, $wrap_column ) = $this -> {'problems'} -> [$i] -> cont_wrap_columns
;
179 my $ignoresign = defined $this -> ignoresigns ?
$this -> ignoresigns
-> [$i] : undef;
180 my @model_header = @
{$this -> {'problems'} -> [$i] -> header
};
181 if ( defined $idcolumn ) {
182 push ( @
{$this -> {'datas'}}, data
->
183 new
( idcolumn
=> $idcolumn,
184 filename
=> $datafile,
185 cont_column
=> $cont_column,
186 wrap_column
=> $wrap_column,
187 #model_header => \@model_header,
188 ignoresign
=> $ignoresign,
189 directory
=> $this -> {'directory'},
190 ignore_missing_files
=> $this -> {'ignore_missing_files'} ||
191 $this -> {'ignore_missing_data'},
192 target
=> $this -> {'target'}) );
194 'debug' -> die( message
=> "Model -> new: Both idcolumn and datafile must ".
195 "be specified to create a model object." );
200 # Read outputfile, if any.
201 if( ! defined $this -> {'outputs'} ) {
202 unless( defined $this -> {'outputfile'} ){
203 ($this -> {'outputfile'} = $this -> {'filename'}) =~ s/\.mod$/.lst/;
205 push ( @
{$this -> {'outputs'}}, output
->
206 new
( filename
=> $this -> {'outputfile'},
207 directory
=> $this -> {'directory'},
208 ignore_missing_files
=>
209 $this -> {'ignore_missing_files'} || $this -> {'ignore_missing_output_files'},
210 target
=> $this -> {'target'},
211 model_id
=> $this -> {'model_id'} ) );
218 # {{{ register_in_database
220 start register_in_database
222 if ( $PsN::config
-> {'_'} -> {'use_database'} ) {
223 # Backslashes messes up the sql syntax
224 my $file_str = $self->{'filename'};
225 my $dir_str = $self->{'directory'};
226 $file_str =~ s/\\/\//g
;
227 $dir_str =~ s/\\/\//g
;
230 my $md5sum = md5_hex
(OSspecific
::slurp_file
($self-> full_name
));
232 my $dbh = DBI
-> connect("DBI:mysql:host=".$PsN::config
-> {'_'} -> {'database_server'}.
233 ";databse=".$PsN::config
-> {'_'} -> {'project'},
234 $PsN::config
-> {'_'} -> {'user'},
235 $PsN::config
-> {'_'} -> {'password'},
236 {'RaiseError' => 1});
243 my $sth = $dbh -> prepare
( "SELECT model_id FROM ".$PsN::config
-> {'_'} -> {'project'}.
245 "WHERE filename = '$file_str' AND ".
246 "directory = '$dir_str' AND ".
247 "md5sum = '".$md5sum."'" );
248 $sth -> execute
or 'debug' -> die( message
=> $sth->errstr ) ;
250 $select_arr = $sth -> fetchall_arrayref
;
253 if ( scalar @
{$select_arr} > 0 ) {
254 'debug' -> warn( level
=> 1,
255 message
=> "Found an old entry in the database matching the ".
256 "current model file" );
257 if ( scalar @
{$select_arr} > 1 ) {
258 'debug' -> warn( level
=> 1,
259 message
=> "Found more than one matching entry in database".
260 ", using the first" );
262 $self -> {'model_id'} = $select_arr->[0][0];
264 my ( $date_str, $time_str );
265 if( $Config{osname
} eq 'MSWin32' ){
266 $date_str = `date /T`;
267 $time_str = ' '.`time /T`;
274 my $date_time = $date_str.$time_str;
275 $sth = $dbh -> prepare
("INSERT INTO ".$PsN::config
-> {'_'} -> {'project'}.
276 ".model (filename,date,directory,md5sum) ".
277 "VALUES ('$file_str', '$date_time', '$dir_str','".
280 $self -> {'model_id'} = $sth->{'mysql_insertid'};
282 $sth -> finish
if ( defined $sth );
285 $model_id = $self -> {'model_id'} # return the model_id;
287 end register_in_database
289 # }}} register_in_database
291 # {{{ shrinkage_stats
293 start shrinkage_stats
295 if ( $#problem_numbers > 0 and ref $enabled eq 'ARRAY' ){
296 if ( $#problem_numbers != ( scalar @
{$enabled} - 1 ) ) {
297 'debug' -> die( message
=> "The number of problem_numbers ".($#problem_numbers+1).
298 "and enabled/disabled shrinkage_stats ".scalar @
{$enabled}.
302 unless( $#problem_numbers > 0 ){
303 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
306 if( ref \
$enabled eq 'SCALAR' ) {
307 for ( @problem_numbers ) {
308 push( @en_arr, $enabled );
310 } elsif ( not ref $enabled eq 'ARRAY' ) {
311 debug
-> die( message
=> 'enabled must be a scalar or a reference to an array, '.
312 'not a reference to a '.ref($enabled).'.' );
315 my @problems = @
{$self -> {'problems'}};
317 foreach my $i ( @problem_numbers ) {
318 if ( defined $problems[ $i-1 ] ) {
319 if ( defined $en_arr[ $j ] ) {
320 if( $en_arr[ $j ] ) {
321 $problems[ $i-1 ] -> shrinkage_module
-> enable
;
323 $problems[ $i-1 ] -> shrinkage_module
-> disable
;
325 # my $eta_file = $self -> filename.'_'.$i.'.etas';
326 # my $eps_file = $self -> filename.'_'.$i.'.wres';
327 # $problems[ $i-1 ] -> {'eta_shrinkage_table'} = $eta_file;
328 # $problems[ $i-1 ] -> {'wres_shrinkage_table'} = $eps_file;
330 push( @indicators, $problems[ $i-1 ] -> shrinkage_module
-> status
);
333 'debug' -> die( message
=> "Problem number $i does not exist!" );
340 # }}} shrinkage_stats
344 =head2 wres_shrinkage
350 my $wres_shrink = $model_object -> wres_shrinkage();
356 Calculates wres shrinkage, a table file with wres is necessary. The
357 return value is reference of and array with one an array per problem
364 my @problems = @
{$self -> {'problems'}};
365 foreach my $problem ( @problems ) {
366 push( @wres_shrinkage, $problem -> wres_shrinkage
);
381 my $eta_shrink = $model_object -> eta_shrinkage();
387 Calculates eta shrinkage, a table file with eta is necessary. The
388 return value is reference of and array with one an array per problem
395 my @problems = @
{$self -> {'problems'}};
396 foreach my $problem ( @problems ) {
397 push( @eta_shrinkage, $problem -> eta_shrinkage
);
404 # {{{ nonparametric_code
406 start nonparametric_code
408 if ( $#problem_numbers > 0 and $#enabled > 0 ){
409 if ( $#problem_numbers != $#enabled ) {
410 'debug' -> die( message
=> "The number of problem_numbers ".($#problem_numbers+1).
411 "and enabled/disabled nonparametric_code ".($#enabled+1).
415 unless( $#problem_numbers > 0 ){
416 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
418 my @problems = @
{$self -> {'problems'}};
420 foreach my $i ( @problem_numbers ) {
421 if ( defined $problems[ $i-1 ] ) {
422 if ( defined $enabled[ $j ] ) {
423 $problems[ $i-1 ] -> nonparametric_code
( $enabled[ $j ] );
425 push( @indicators, $problems[ $i-1 ] -> nonparametric_code
);
428 'debug' -> die( message
=> "Problem number $i does not exist!" );
433 end nonparametric_code
435 # }}} nonparametric_code
437 # {{{ add_nonparametric_code
439 start add_nonparametric_code
441 $self -> set_records
( type
=> 'nonparametric',
442 record_strings
=> [ 'MARGINALS UNCONDITIONAL' ] );
443 $self -> set_option
( record_name
=> 'estimation',
444 option_name
=> 'POSTHOC' );
445 my ( $msfo_ref, $junk ) = $self ->
446 _get_option_val_pos
( name
=> 'MSFO',
447 record_name
=> 'estimation' );
448 my @nomegas = @
{$self -> nomegas
};
450 for( my $i = 0; $i <= $#nomegas; $i++ ) { # loop the problems
452 for( my $j = 0; $j <= $nomegas[$i]; $j++ ) {
453 $marg_str = $marg_str.' COM('.($j+1).')=MG'.($j+1);
455 $marg_str = $marg_str.' FILE='.$self->filename.'.marginals'.
456 ' NOAPPEND ONEHEADER NOPRINT';
457 $self -> add_records
( problem_numbers
=> [($i+1)],
459 record_strings
=> [ $marg_str ] );
460 $self -> remove_option
( record_name
=> 'abbreviated',
461 option_name
=> 'COMRES' );
462 $self -> add_option
( record_name
=> 'abbreviated',
463 option_name
=> 'COMRES',
464 option_value
=> ($nomegas[$i]+1),
465 add_record
=> 1 ); #Add $ABB if not existing
467 $self -> add_marginals_code
( problem_numbers
=> [($i+1)],
468 nomegas
=> [ $nomegas[$i] ] );
471 if( not defined $msfo_ref ) {
472 for( my $i = 0; $i < $self -> nproblems
; $i++ ) {
473 $self -> add_option
( record_name
=> 'estimation',
474 option_name
=> 'MSFO',
475 option_value
=> $self -> filename
.'.msfo'.($i+1) );
478 for( my $i = 0; $i < scalar @
{$msfo_ref}; $i++ ) {
479 if( not defined $msfo_ref->[$i] or not defined $msfo_ref->[$i][0] ) {
480 $self -> add_option
( record_name
=> 'estimation',
481 option_name
=> 'MSFO',
482 option_value
=> $self -> filename
.'.msfo'.($i+1) );
487 end add_nonparametric_code
489 # }}} add_nonparametric_code
499 $model_object -> flush_data();
505 flush data calls the same method on each data object (usually one)
506 which causes it to write data to disk and remove its data from memory.
512 if ( defined $self -> {'datas'} ) {
513 foreach my $data ( @
{$self -> {'datas'}} ) {
528 C<< my $file_name = $model_object -> full_name(); >>
532 full_name will return the name of the modelfile and its directory in a
533 string. For example: "/users/guest/project/model.mod".
539 $full_name = $self -> {'directory'} . $self -> {'filename'};
547 This function is unused
and should probably be removed
.
549 # start __sync_output
551 unless( defined $self -> {'outputfile'} ){
552 'debug' -> die( message
=> "No output file is set, cannot synchronize output" );
554 @
{$self -> {'outputs'}} = ();
555 push ( @
{$self -> {'outputs'}}, output
->
556 new
( filename
=> $self -> {'outputfile'},
557 ignore_missing_files
=> $self -> {'ignore_missing_files'},
558 target
=> $self -> {'target'},
559 model_id
=> $self -> {'model_id'} ) );
565 # {{{ add_marginals_code
567 start add_marginals_code
569 # add_marginals_code takes two arguments.
571 # - problem_numbers is an array holding the numbers of the problems in
572 # which code should be added.
574 # - nomegas which is an array holding the number of (diagonal-element)
575 # omegas of each problem given by problem_numbers.
577 # For each omega in each problem, verbatim code is added to make the
578 # marginals available for printing (e.g. to a table file). COM(1) will
579 # hold the nonparametric density, COM(2) the marginal cumulative value
580 # for the first eta, COM(2) the marginal cumulative density for the
581 # second eta and so on.
583 unless( $#problem_numbers >= 0 ){
584 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
587 my @problems = @
{$self -> {'problems'}};
589 foreach my $i ( @problem_numbers ) {
590 if ( defined $problems[ $i-1 ] ) {
591 $problems[$i-1] -> add_marginals_code
( nomegas
=> $nomegas[ $j ] );
593 'debug' -> die( message
=> "Problem number $i does not exist.");
598 end add_marginals_code
600 # }}} add_marginals_code
610 $model_object -> add_records( type => 'THETA',
611 record_strings => ['(0.1,15,23)'] );
627 =item problem_numbers
635 add_records is used to add NONMEM control file records to the model
636 object. The "type" argument is mandatory and must be a valid NONMEM
637 record name, such as "PRED" or "THETA". Otherwise an error will be
638 output and the program terminated (this is object to change, ideally
639 we would only report an error and let the caller deal with it). The
640 "record_strings" argument is a mandatory array of valid NONMEM record
641 code. Each array corresponds to a line of the record code. There
642 "problem_numbers" argument is optional and is an array of problems
643 numbered from 1 for which the record is added, by default the record
644 is added to all problems.
646 Notice that the records are appended to those that allready exists,
647 which makes sence for records that do not exist and for initial
648 values. For records like "DATA" or "PRED" you probably want to use
655 unless( $#problem_numbers >= 0 ){
656 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
659 my @problems = @
{$self -> {'problems'}};
660 foreach my $i ( @problem_numbers ) {
661 if ( defined $problems[ $i-1 ] ) {
662 # if( defined $self -> {'problems'} ){
663 # if( defined @{$self -> {'problems'}}[$problem_number - 1] ){
664 # my $problem = @{$self -> {'problems'}}[$problem_number - 1];
665 # $problem -> add_records( 'type' => $type,
666 # 'record_strings' => \@record_strings );
667 $problems[$i-1] -> add_records
( 'type' => $type,
668 'record_strings' => \
@record_strings );
670 'debug' -> die( message
=> "Problem number $i does not exist.");
674 # 'debug' -> die( message => "Model -> add_records: No Problems in model object.") ;
689 $model_object -> set_records( type => 'THETA',
690 record_strings => ['(0.1,15,23)'] );
706 =item problem_numbers
714 set_records works just like add_records but will replace any existing
715 records in the model object.
721 unless( $#problem_numbers >= 0 ){
722 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
725 my @problems = @
{$self -> {'problems'}};
726 foreach my $i ( @problem_numbers ) {
727 if ( defined $problems[ $i-1 ] ) {
728 # if( defined $self -> {'problems'} ){
729 # if( defined @{$self -> {'problems'}}[$problem_number - 1] ){
730 # my $problem = @{$self -> {'problems'}}[$problem_number - 1];
731 # $problem -> set_records( 'type' => $type,
732 # 'record_strings' => \@record_strings );
733 $problems[$i-1] -> set_records
( 'type' => $type,
734 'record_strings' => \
@record_strings );
736 'debug' -> die( "Problem number $i does not exist." );
740 # 'debug' -> die( "No Problems in model object.") ;
749 =head2 remove_records
755 $model_object -> remove_records( type => 'THETA' )
767 =item problem_numbers
775 remove_records removes the record given in the "type" argument which
776 must be a valid NONMEM record name.
782 unless( $#problem_numbers >= 0 ){
783 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
786 my @problems = @
{$self -> {'problems'}};
787 foreach my $i ( @problem_numbers ) {
788 if ( defined $problems[ $i-1 ] ) {
789 # if( defined $self -> {'problems'} ){
790 # if( defined @{$self -> {'problems'}}[$problem_number - 1] ){
791 # my $problem = @{$self -> {'problems'}}[$problem_number - 1];
792 # $problem -> remove_records( 'type' => $type );
793 $problems[$i-1] -> remove_records
( 'type' => $type );
795 'debug' -> die( message
=> "Problem number $i, does not exist" );
799 # 'debug' -> die( message => "No Problems in model object." );
814 $model_object -> copy( filename => 'copy.mod',
840 =item data_file_names
846 string with value 'disk' or 'mem'
848 =item extra_data_file_names
852 =item update_shrinkage_tables
860 copy produces a new modelfile object and a new file on disk whose name
861 is given by the "filename" argument. To create copies of data file the
862 copy_data options may be set to 1. The values of "data_file_names",
863 unless given, will be the model file name but with '.mod' exchanged
864 for '_$i.dta', where $i is the problem number. If data is not copied,
865 a new data object will be intialized from the same data file as the
866 previous model and "data_file_names" WILL BE IGNORED. This has the
867 side effect that the data file can be modified from both the original
868 model and the copy. The same holds for "extra_data_files". It is
869 possible to set "copy_output" to 1 as well, which then copies the
870 output object instead of reading the output file from disk, which is
871 slower. Since output objects are meant to be read-only, no
872 output_filename can be specified and the output object copy will
873 reside in memory only.
875 The "target" option has no effect.
881 # PP_TODO fix a nice copying of modelfile data
882 # preferably in memory copy. Perhaps flush data ?
884 # Check sanity of the length of data file names argument
885 if ( scalar @data_file_names > 0 ) {
886 'debug' -> die( message
=> "model -> copy: The number of specified new data file " .
887 "names ". scalar @data_file_names. "must\n match the number".
888 " of data objects connected to the model object".
889 scalar @
{$self -> {'datas'}} )
890 unless ( scalar @data_file_names == scalar @
{$self -> {'datas'}} );
893 ($d_filename = $filename) =~ s/\.mod$//;
894 for ( my $i = 1; $i <= scalar @
{$self -> {'datas'}}; $i++ ) {
895 # Data filename is created in this directory (no directory needed).
896 push( @data_file_names, $d_filename."_data_".$i."_copy.dta" );
900 # Check sanity of the length of extra_data file names argument
901 if ( scalar @extra_data_file_names > 0 ) {
902 'debug' -> die( message
=> "The number of specified new extra_data file ".
903 "names ". scalar @extra_data_file_names, "must\n match the number".
904 " of problems (one extra_data file per prolem)".
905 scalar @
{$self -> {'extra_data_files'}} )
906 unless( scalar @extra_data_file_names == scalar @
{$self -> {'extra_data_files'}} );
908 if ( defined $self -> {'extra_data_files'} ) {
910 ($d_filename = $filename) =~ s/\.mod$//;
911 for ( my $i = 1; $i <= scalar @
{$self -> {'extra_data_files'}}; $i++ ) {
912 # Extra_Data filename is created in this directory (no directory needed).
913 push( @extra_data_file_names, $d_filename."_extra_data_".$i."_copy.dta" );
918 ($directory, $filename) = OSspecific
::absolute_path
( $directory, $filename );
922 # save references to own data and output objects
923 my $datas = $self -> {'datas'};
924 # $Data::Dumper::Maxdepth = 2;
925 # die "MC1: ", Dumper $datas -> [0] -> {'individuals'};
926 my $outputs = $self -> {'outputs'};
928 my @problems = @
{$self -> {'problems'}};
929 for ( my $i = 0; $i <= $#problems; $i++ ) {
930 if ( defined $problems[$i] -> {'extra_data'} ) {
931 $extra_datas{$i} = $problems[$i] -> {'extra_data'};
935 my ( @new_datas, @new_extra_datas, @new_outputs );
937 $self -> synchronize
if not $self -> {'synced'};
939 # remove ref to data and output object to speed up the
941 $self -> {'datas'} = undef;
942 $self -> {'outputs'} = undef;
943 for ( my $i = 0; $i <= $#problems; $i++ ) {
944 $problems[$i] -> {'extra_data'} = undef;
947 # Copy the data objects if so is requested
948 if ( defined $datas ) {
950 foreach my $data ( @
{$datas} ) {
951 if ( $copy_data == 1 ) {
952 push( @new_datas, $data ->
953 copy
( filename
=> $data_file_names[$i]) );
955 # This line assumes one data per problem! May be a source of error.
956 my ( $cont_column, $wrap_column ) = $self -> problems
-> [$i] -> cont_wrap_columns
;
957 my $ignoresign = defined $self -> ignoresigns ?
$self -> ignoresigns
-> [$i] : undef;
958 my @model_header = @
{$self -> problems
-> [$i] -> header
};
959 push @new_datas, data
->
960 new
( filename
=> $data -> filename
,
961 directory
=> $data -> directory
,
962 cont_column
=> $cont_column,
963 wrap_column
=> $wrap_column,
964 #model_header => \@model_header,
966 ignoresign
=> $ignoresign,
967 idcolumn
=> $data -> idcolumn
);
973 # Copy the extra_data objects if so is requested
974 for ( my $i = 0; $i <= $#problems; $i++ ) {
975 my $extra_data = $extra_datas{$i};
976 if ( defined $extra_data ) {
977 if ( $copy_data == 1 ) {
978 push( @new_extra_datas, $extra_data ->
979 copy
( filename
=> $extra_data_file_names[$i]) );
981 push( @new_extra_datas, extra_data
->
982 new
( filename
=> $extra_data -> filename
,
983 directory
=> $extra_data -> directory
,
985 idcolumn
=> $extra_data -> idcolumn
) );
991 # Clone self into new model object and set synced to 0 for
993 $new_model = Storable
::dclone
( $self );
994 $new_model -> {'synced'} = 0;
996 # $Data::Dumper::Maxdepth = 3;
997 # die Dumper $new_datas[0] -> {'individuals'};
999 # Restore the data and output objects for self
1000 $self -> {'datas'} = $datas;
1001 $self -> {'outputs'} = $outputs;
1002 for ( my $i = 0; $i <= $#problems; $i++ ) {
1003 if( defined $extra_datas{$i} ){
1004 $problems[$i] -> {'extra_data'} = $extra_datas{$i};
1008 # Set the new file name for the copy
1009 $new_model -> directory
( $directory );
1010 $new_model -> filename
( $filename );
1012 # {{{ update the shrinkage modules
1014 my @problems = @
{$new_model -> problems
};
1015 for( my $i = 1; $i <= scalar @problems; $i++ ) {
1016 $problems[ $i-1 ] -> shrinkage_module
-> model
( $new_model );
1019 # }}} update the shrinkage modules
1021 # Copy the output object if so is requested (only one output
1022 # object defined per model object)
1023 if ( defined $outputs ) {
1024 foreach my $output ( @
{$outputs} ) {
1025 if ( $copy_output == 1 ) {
1026 push( @new_outputs, $output -> copy
);
1028 my $new_out = $filename;
1029 $new_out =~ s/\.mod$/\.lst/;
1030 push( @new_outputs, output
->
1031 new
( filename
=> $new_out,
1032 directory
=> $directory,
1034 ignore_missing_files
=> 1,
1035 model_id
=> $new_model -> {'model_id'} ) );
1040 # Add the copied data and output objects to the model copy
1041 $new_model -> datas
( \
@new_datas );
1043 if ( $#new_extra_datas >= 0 ) {
1044 my @new_problems = @
{$new_model -> problems
};
1045 for ( my $i = 0; $i <= $#new_problems; $i++ ) {
1046 $new_problems[$i] -> {'extra_data'} = $new_extra_datas[$i];
1047 if ( $copy_data == 1 ){
1048 $new_problems[$i] -> {'extra_data_file_name'} = $extra_data_file_names[$i];
1053 $new_model -> {'outputs'} = \
@new_outputs;
1055 $new_model -> _write
;
1057 $new_model -> synchronize
if $target eq 'disk';
1071 my $indicators = $model_object -> covariance( enabled => [1] );
1083 =item problem_numbers
1091 covariance will let you turn the covariance step on and off per
1092 problem. The "enabled" argument is an array which must have a length
1093 equal to the number of problems. Each element set to 0 will disable
1094 the covariance step for the corresponding problem. And conversely each
1095 element set to nonzero will enable the covariance step.
1097 covariance will return an array with an element for each problem, the
1098 element will indicate whether the covariance step is turned on or not.
1104 if ( $#problem_numbers > 0 ){
1105 if ( $#problem_numbers != $#enabled ) {
1106 'debug' -> die( message
=> "The number of problem_numbers ".($#problem_numbers+1).
1107 "and enabled/disabled covariance records ".($#enabled+1).
1111 unless( $#problem_numbers > 0 ){
1112 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
1114 my @problems = @
{$self -> {'problems'}};
1116 foreach my $i ( @problem_numbers ) {
1117 if ( defined $problems[ $i-1 ] ) {
1118 if ( defined $enabled[ $j ] ) {
1119 $problems[ $i-1 ] -> covariance
( enabled
=> $enabled[ $j ] );
1121 push( @indicators, $problems[ $i-1 ] -> covariance
);
1124 'debug' -> die( message
=> "Problem number $i does not exist!" );
1141 $model_object -> datas( [$data_obj] );
1143 my $data_objects = $model_object -> data;
1149 The argument is an unnamed array of data objects.
1153 If data is used without argument the data objects connected to the
1154 model object is returned. If an argument is given it must be an array
1155 of length equal to the number of problems with data objects. Those
1156 objects will replace any existing data objects and their filenames
1157 will be put in the model files records.
1163 my $nprobs = scalar @
{$self -> {'problems'}};
1164 if ( defined $parm ) {
1165 if ( ref($parm) eq 'ARRAY' ) {
1166 my @new_datas = @
{$parm};
1167 # Check that new_headers and problems match
1168 'debug' -> die( message
=> "The number of problems $nprobs and".
1169 " new data ". $#new_datas+1 ." don't match in ".
1170 $self -> full_name
) unless ( $#new_datas + 1 == $nprobs );
1171 if ( defined $self -> {'problems'} ) {
1172 for( my $i = 0; $i < $nprobs; $i++ ) {
1173 $self -> _option_name
( position
=> 0,
1175 problem_number
=> $i+1,
1176 new_name
=> $new_datas[$i] -> filename
);
1179 'debug' -> die( message
=> "No problems defined in ".
1180 $self -> full_name
);
1183 'debug' -> die( message
=> "Supplied new value is not an array" );
1194 # I have removed this because it was only used in the bootstrap. I
1195 # fixed the bootstrap to use datafiles instead. Also the bootstrap
1196 # methods who used this was very old and should probably be removed as
1201 # datafile either retrieves or sets a new name for the datafile in the first problem of the
1202 # model. This method is only here for compatibility reasons. Don't use it. Use L</datafiles> instead.
1204 if( defined $new_name ){
1205 $self -> _option_name
( position
=> 0,
1207 problem_number
=> $problem_number,
1208 new_name
=> $new_name);
1209 my ( $cont_column, $wrap_column ) = $self -> problems
-> [$problem_number-1] ->
1211 my $ignoresign = defined $self -> ignoresigns ?
1212 $self -> ignoresigns
-> [$problem_number-1] : undef;
1213 my @model_header = @
{$self -> problems
-> [$problem_number-1] -> header
};
1214 $self -> {'datas'} -> [$problem_number-1] = data
->
1215 new
( idcolumn
=> $self -> idcolumn
( problem_number
=> $problem_number ),
1216 ignoresign
=> $ignoresign,
1217 filename
=> $new_name,
1218 cont_column
=> $cont_column,
1219 wrap_column
=> $wrap_column,
1220 #model_header => \@model_header,
1221 ignore_missing_files
=> $self -> {'ignore_missing_files'},
1222 target
=> $self -> {'target'} );
1224 $name = $self -> _option_name
( position
=> 0, record
=> 'data', problem_number
=> $problem_number );
1239 $model_object -> datafiles( new_names => ['datafile.dta'] );
1251 =item problem_numbers
1263 datafiles changes the names of the data files in a model file. The
1264 "new_names" argument is an array of strings, where each string gives
1265 the file name of a problem data file. The length of "new_names" must
1266 be equal to the "problem_numbers" argument. "problem_numbers" is by
1267 default containing all of the models problems numbers. In the example
1268 above we only have one problem in the model file and therefore only
1269 need to give on new file name.
1271 Unless new_names is given datafiles returns the names of the data
1272 files used by the model file. If the optional "absolute_path" argument
1273 is given, the returned file names will have the path to file as well.
1279 # The datafiles method retrieves or sets the names of the
1280 # datafiles specified in the $DATA record of each problem. The
1281 # problem_numbers argument can be used to control which
1282 # problem that is affected. If absolute_path is set to 1, the
1283 # returned file names are given with absolute paths.
1285 unless( $#problem_numbers > 0 ){
1286 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
1288 if ( scalar @new_names > 0 ) {
1290 my @idcolumns = @
{$self ->
1291 idcolumns
( problem_numbers
=> \
@problem_numbers )};
1292 foreach my $new_name ( @new_names ) {
1293 if ( $absolute_path ) {
1295 ($tmp, $new_name) = OSspecific
::absolute_path
('', $new_name );
1296 $new_name = $tmp . $new_name;
1299 $self -> _option_name
( position
=> 0,
1301 problem_number
=> $problem_numbers[$i],
1302 new_name
=> $new_name);
1303 my ( $cont_column, $wrap_column ) = $self -> problems
->
1304 [$problem_numbers[$i]-1] -> cont_wrap_columns
;
1305 my $ignoresign = defined $self -> ignoresigns ?
$self -> ignoresigns
-> [$i] : undef;
1306 my @model_header = @
{$self -> problems
-> [$i] -> header
};
1307 $self -> {'datas'} -> [$problem_numbers[$i]-1] = data
->
1308 new
( idcolumn
=> $idcolumns[$i],
1309 ignoresign
=> $ignoresign,
1310 filename
=> $new_name,
1311 cont_column
=> $cont_column,
1312 wrap_column
=> $wrap_column,
1313 #model_header => \@model_header,
1314 ignore_missing_files
=> $self -> {'ignore_missing_files'},
1315 target
=> $self -> {'target'} );
1319 foreach my $prob_num ( @problem_numbers ) {
1320 if ( $absolute_path ) {
1321 my ($d_dir, $d_name);
1323 OSspecific
::absolute_path
($self -> {'directory'}, $self ->_option_name( position
=> 0,
1325 problem_number
=> $prob_num ) );
1326 push( @names, $d_dir . $d_name );
1328 my $name = $self -> _option_name
( position
=> 0,
1330 problem_number
=> $prob_num );
1331 $name =~ s/.*[\/\\]//;
1332 push( @names, $name );
1344 # This method is renamed __des in dia but not here. If nothing broke
1345 # until now I think we can safely remove it.
1349 # Returns the des part specified subproblem.
1350 # TODO: Even though new_des can be specified, they wont be set
1353 my @prob = @
{$self -> problems
};
1354 my @des = @
{$prob[$problem_number - 1] -> get_record
('des') -> code
}
1355 if ( defined $prob[$problem_number - 1] -> get_record
('des') );
1364 $self -> {'problems'} -> [0] -> eigen
;
1372 # This method is renamed __error in dia but not here. If nothing broke
1373 # until now I think we can safely remove it.
1379 # @error = $modelObject -> error;
1381 # Returns the error part specified subproblem.
1382 # TODO: Even though new_error can be specified, they wont be set
1384 my @prob = @
{$self -> problems
};
1385 my @error = @
{$prob[0] -> get_record
('error') -> code
}
1386 if ( defined $prob[0] -> get_record
('error') );
1392 # {{{ extra_data_files
1394 =head2 extra_data_files
1400 $model_object -> extra_data_files( ['extra_data.dta'] );
1402 my $extra_file_name = $model_object -> extra_data_files;
1408 The argument is an unnamed array of strings
1412 If extra_data_files is used without argument the names of any extra
1413 data files connected to the model object is returned. If an argument
1414 is given it must be an array of length equal to the number of problems
1415 in the model. Then the names of the extra data files will be changed
1416 to those in the array.
1420 start extra_data_files
1423 # Sets or retrieves extra_data_file_name on problem level
1424 my $nprobs = scalar @
{$self -> {'problems'}};
1425 if ( defined $parm ) {
1426 if ( ref($parm) eq 'ARRAY' ) {
1427 my @new_file_names = @
{$parm};
1428 # Check that new_file_names and problems match
1429 'debug' -> die( message
=> "model -> extra_data_files: The number of problems $nprobs and" .
1430 " new_file_names " . $#new_file_names+1 . " don't match in ".
1431 $self -> full_name
) unless ( $#new_file_names + 1 == $nprobs );
1432 if ( defined $self -> {'problems'} ) {
1433 for( my $i = 0; $i < $nprobs; $i++ ) {
1434 $self -> {'problems'} -> [$i] -> extra_data_file_name
( $new_file_names[$i] );
1437 'debug' -> die( message
=> "No problems defined in " .
1438 $self -> full_name
);
1441 'debug' -> die(message
=> "Supplied new value is not an array.");
1444 if ( defined $self -> {'problems'} ) {
1445 for( my $i = 0; $i < $nprobs; $i++ ) {
1446 if( defined $self -> {'problems'} -> [$i] -> extra_data_file_name
) {
1447 push ( @file_names ,$self -> {'problems'} -> [$i] -> extra_data_file_name
);
1452 return \
@file_names;
1454 end extra_data_files
1458 # {{{ extra_data_headers
1460 =head2 extra_data_headers
1466 $model_object -> extra_data_headers( [$data_obj] );
1468 my $data_objects = $model_object -> extra_data_headers;
1474 The argument is an unnamed array of arrays of strings.
1478 If extra_data_files is used without argument the headers of any extra
1479 data files connected to the model object is returned. If an argument
1480 is given it must be an array of length equal to the number of problems
1481 in the model. Then the headers of the extra data files will be changed
1482 to those in the array.
1486 start extra_data_headers
1489 # Sets or retrieves extra_data_header on problem level
1490 my $nprobs = scalar @
{$self -> {'problems'}};
1491 if ( defined $parm ) {
1492 if ( ref($parm) eq 'ARRAY' ) {
1493 my @new_headers = @
{$parm};
1494 # Check that new_headers and problems match
1495 'debug' -> die( message
=> "The number of problems $nprobs and".
1496 " new_headers " . $#new_headers+1 . " don't match in ".
1497 $self -> full_name
) unless ( $#new_headers + 1 == $nprobs );
1498 if ( defined $self -> {'problems'} ) {
1499 for( my $i = 0; $i < $nprobs; $i++ ) {
1500 $self -> {'problems'} -> [$i] -> extra_data_header
( $new_headers[$i] );
1503 'debug' -> die( message
=> "No problems defined in " . $self -> full_name
);
1506 'debug' -> die( message
=> "Supplied new value is not an array" );
1509 if ( defined $self -> {'problems'} ) {
1510 for( my $i = 0; $i < $nprobs; $i++ ) {
1511 push ( @headers, $self -> {'problems'} -> [$i] -> extra_data_header
);
1517 end extra_data_headers
1519 # }}} extra_data_headers
1529 my $factors = $model_object -> factors;
1545 =item problem_number
1549 =item return_occurences
1553 =item unique_in_individual
1561 The following text comes from the documentation of
1562 data::factors. model::factors will call data::factors for the given
1563 problem number in the model object. Also it will take try to find
1564 "column_head" in the $INPUT record instead of the data file header.
1566 Either column (number, starting at 1) or column_head must be
1567 specified. The default behaviour is to return a hash with the factors
1568 as keys referencing arrays with the order numbers (not the ID numbers)
1569 of the individuals that contain this factor.
1571 If unique_in_individual is true (1), the returned hash will contain an
1572 element with key 'Non-unique values found' and value 1 if any
1573 individual contain more than one value in the specified column.
1575 Return occurences will calculate the occurence of each factor
1576 value. Several occurences in one individual counts as one
1577 occurence. The elements of the returned hash will have the factors as
1578 keys and the number of occurences as values.
1584 # Calls <I>factors</I> on the data object of a specified
1585 # problem. See <I>data -> factors</I> for details.
1587 my $extra_data_column;
1588 if ( defined $column_head ) {
1589 # Check normal data object first
1590 my ( $values_ref, $positions_ref ) = $self ->
1591 _get_option_val_pos
( problem_numbers
=> [$problem_number],
1592 name
=> $column_head,
1593 record_name
=> 'input',
1594 global_position
=> 1 );
1595 $column_number = $positions_ref -> [0];
1596 # Next, check extra_data
1597 my $extra_data_headers = $self -> extra_data_headers
;
1598 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
1599 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
1600 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
1603 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
1604 unless ( defined $column_number or defined $extra_data_column );
1606 $column_number = $column;
1608 if ( defined $column_number) {
1609 %factors = %{$self -> {'datas'} -> [$problem_number-1] ->
1610 factors
( column
=> $column_number,
1611 unique_in_individual
=> $unique_in_individual,
1612 return_occurences
=> $return_occurences )};
1614 %factors = %{$self -> {'problems'} -> [$problem_number-1] -> extra_data
1615 -> factors
( column
=> $extra_data_column,
1616 unique_in_individual
=> $unique_in_individual,
1617 return_occurences
=> $return_occurences )};
1632 my $fractions = $model_object -> fractions;
1648 =item problem_number
1652 =item return_occurences
1656 =item ignore_missing
1664 fractions will return the fractions from data::fractions. It will find
1665 "column_head" in the $INPUT record instead of that data header as
1666 data::fractions does.
1672 # Calls <I>fractions</I> on the data object of a specified
1673 # problem. See <I>data -> fractions</I> for details.
1675 my $extra_data_column;
1676 if ( defined $column_head ) {
1677 # Check normal data object first
1678 my ( $values_ref, $positions_ref ) = $self ->
1679 _get_option_val_pos
( problem_numbers
=> [$problem_number],
1680 name
=> $column_head,
1681 record_name
=> 'input',
1682 global_position
=> 1 );
1683 $column_number = $positions_ref -> [0];
1684 # Next, check extra_data
1685 my $extra_data_headers = $self -> extra_data_headers
;
1686 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
1687 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
1688 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
1691 'debug' -> die( "Unknown column \"$column_head\"" )
1692 unless ( defined $column_number or defined $extra_data_column );
1694 $column_number = $column;
1696 if ( defined $column_number) {
1697 %fractions = %{$self -> {'datas'} -> [$problem_number-1] ->
1698 fractions
( column
=> $column_number,
1699 unique_in_individual
=> $unique_in_individual,
1700 ignore_missing
=> $ignore_missing )};
1702 %fractions = %{$self -> {'problems'} -> [$problem_number-1] -> extra_data
1703 -> fractions
( column
=> $extra_data_column,
1704 unique_in_individual
=> $unique_in_individual,
1705 ignore_missing
=> $ignore_missing )};
1720 my $fractions = $model_object -> fractions;
1736 =item problem_number
1740 =item return_occurences
1744 =item ignore_missing
1752 fractions will return the fractions from data::fractions. It will find
1753 "column_head" in the $INPUT record instead of that data header as
1754 data::fractions does.
1760 # Sets or gets the 'fixed' status of a (number of)
1761 # parameter(s). 1 correspond to a parameter being fixed and
1762 # 0 not fixed. The returned parameter is a reference to a
1763 # two-dimensional array, indexed by problems and parameter
1765 # Valid parameter types are 'theta', 'omega' and 'sigma'.
1767 @fixed = @
{ $self -> _init_attr
1768 ( parameter_type
=> $parameter_type,
1769 parameter_numbers
=> \
@parameter_numbers,
1770 problem_numbers
=> \
@problem_numbers,
1771 new_values
=> \
@new_values,
1772 attribute
=> 'fix')};
1778 # {{{ have_missing_data
1786 my $fractions = $model_object -> fractions;
1802 =item problem_number
1806 =item return_occurences
1810 =item ignore_missing
1818 fractions will return the fractions from data::fractions. It will find
1819 "column_head" in the $INPUT record instead of that data header as
1820 data::fractions does.
1824 start have_missing_data
1826 # Calls <I>have_missing_data</I> on the data object of a specified
1827 # problem. See <I>data -> have_missing_data</I> for details.
1829 my $extra_data_column;
1830 if ( defined $column_head ) {
1831 # Check normal data object first
1832 my ( $values_ref, $positions_ref ) = $self ->
1833 _get_option_val_pos
( problem_numbers
=> [$problem_number],
1834 name
=> $column_head,
1835 record_name
=> 'input',
1836 global_position
=> 1 );
1837 $column_number = $positions_ref -> [0];
1838 # Next, check extra_data
1839 my $extra_data_headers = $self -> extra_data_headers
;
1840 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
1841 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
1842 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
1845 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
1846 unless ( defined $column_number or defined $extra_data_column );
1848 $column_number = $column;
1850 if ( defined $column_number) {
1851 $return_value = $self -> {'datas'} -> [$problem_number-1] ->
1852 have_missing_data
( column
=> $column_number );
1854 $return_value = $self -> {'problems'} -> [$problem_number-1] ->
1855 extra_data
-> have_missing_data
( column
=> $extra_data_column );
1858 end have_missing_data
1870 my $fractions = $model_object -> fractions;
1886 =item problem_number
1890 =item return_occurences
1894 =item ignore_missing
1902 fractions will return the fractions from data::fractions. It will find
1903 "column_head" in the $INPUT record instead of that data header as
1904 data::fractions does.
1912 # @idcolumns = @{$modelObject -> idcolumns( problem_numbers => [2,3] );
1914 # idcolumns returns the idcolumn index in the datafile for the
1915 # specified problem.
1918 ( $junk_ref, $col ) = $self ->
1919 _get_option_val_pos
( name
=> 'ID',
1920 record_name
=> 'input',
1921 problem_numbers
=> [$problem_number] );
1923 if ( $problem_number ne 'all' ) {
1939 my $fractions = $model_object -> fractions;
1955 =item problem_number
1959 =item return_occurences
1963 =item ignore_missing
1971 fractions will return the fractions from data::fractions. It will find
1972 "column_head" in the $INPUT record instead of that data header as
1973 data::fractions does.
1981 # @column_numbers = @{$modelObject -> idcolumns( problem_numbers => [2] )};
1983 # idcolumns returns the idcolumn indexes in the datafile for the
1984 # specified problems.
1986 my ( $junk_ref, $col_ref ) = $self ->
1987 _get_option_val_pos
( name
=> 'ID',
1988 record_name
=> 'input',
1989 problem_numbers
=> \
@problem_numbers );
1990 # There should only be one instance of $INPUT and hence we collapse
1991 # the two-dim return from _get_option_pos_val to a one-dim array:
1993 foreach my $prob ( @
{$col_ref} ) {
1994 foreach my $inst ( @
{$prob} ) {
1995 push( @column_numbers, $inst );
2010 my $fractions = $model_object -> fractions;
2026 =item problem_number
2030 =item return_occurences
2034 =item ignore_missing
2042 fractions will return the fractions from data::fractions. It will find
2043 "column_head" in the $INPUT record instead of that data header as
2044 data::fractions does.
2052 # @ignore_signs = @{$modelObject -> ignoresigns( problem_numbers => [2,4] )};
2054 # ignoresigns returns the ignore signs in the datafile for the
2055 # specified problems
2057 my ( $ignore_opt_ref, $junk_ref ) = $self ->
2058 _get_option_val_pos
( name
=> 'IGNORE',
2059 record_name
=> 'data',
2060 problem_numbers
=> \
@problem_numbers );
2062 # There should only be one instance of $DATA and hence we collapse
2063 # the two-dim return from _get_option_pos_val to a one-dim array:
2064 foreach my $prob ( @
{$ignore_opt_ref} ) {
2065 foreach my $inst ( @
{$prob} ) {
2066 $inst = '#' unless defined $inst;
2067 push( @ignore, $inst );
2083 my $fractions = $model_object -> fractions;
2099 =item problem_number
2103 =item return_occurences
2107 =item ignore_missing
2115 fractions will return the fractions from data::fractions. It will find
2116 "column_head" in the $INPUT record instead of that data header as
2117 data::fractions does.
2125 # @indexArray = @{$modelObject -> indexes( 'parameter_type' => 'omega' )};
2127 # A call to I<indexes> returns the indexes of all parameters
2128 # specified in I<parameter_numbers> from the subproblems
2129 # specified in I<problem_numbers>. The method returns a reference to an array that has
2130 # the same structure as parameter_numbers but for each
2131 # array of numbers is instead an array of indices. The method
2132 # uses a method from the model::problem class to format the
2133 # indices, so here are a few lines from the code comments in
2134 # model/problem.pm that describes the returned value:
2137 # The Indexes method calculates the index for a
2138 # parameter. Off-diagonal elements will get a index 'i_j', where i
2139 # is the row number and j is the column number
2142 unless( $#problem_numbers > 0 ){
2143 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
2145 my @problems = @
{$self -> {'problems'}};
2146 foreach my $i ( @problem_numbers ) {
2147 if ( defined $problems[ $i-1 ] ) {
2149 $problems[ $i-1 ] ->
2150 indexes
( parameter_type
=> $parameter_type,
2151 parameter_numbers
=> $parameter_numbers[ $i-1 ] ) );
2153 'debug' -> die( message
=> "Problem number $i does not exist!" );
2161 # {{{ initial_values
2169 my $fractions = $model_object -> fractions;
2185 =item problem_number
2189 =item return_occurences
2193 =item ignore_missing
2201 fractions will return the fractions from data::fractions. It will find
2202 "column_head" in the $INPUT record instead of that data header as
2203 data::fractions does.
2207 start initial_values
2209 # initial_values either sets or gets the initial values of
2210 # the parameter specified in "parameter_type" for each
2211 # problem specified in problem_numbers. For each element
2212 # in problem_numbers there must be a reference in
2213 # parameter_numbers to an array that specify the indices
2214 # of the parameters in the subproblem for which the initial
2215 # values are set, replaced or retrieved.
2217 # The add_if_absent argument tells the method to add an init
2218 # (theta,omega,sigma) if the parameter number points to a
2219 # non-existing parameter with parameter number one higher
2220 # than the highest presently included. Only applicable if
2221 # new_values are set. Valid parameter types are 'theta',
2222 # 'omega' and 'sigma'.
2224 @initial_values = @
{ $self -> _init_attr
2225 ( parameter_type
=> $parameter_type,
2226 parameter_numbers
=> \
@parameter_numbers,
2227 problem_numbers
=> \
@problem_numbers,
2228 new_values
=> \
@new_values,
2229 attribute
=> 'init',
2230 add_if_absent
=> $add_if_absent )};
2234 # }}} initial_values
2245 my $fractions = $model_object -> fractions;
2261 =item problem_number
2265 =item return_occurences
2269 =item ignore_missing
2277 fractions will return the fractions from data::fractions. It will find
2278 "column_head" in the $INPUT record instead of that data header as
2279 data::fractions does.
2287 # if( $modelObject -> is_option_set( record => 'recordName', name => 'optionName' ) ){
2288 # print "problem_number 1 has option optionName set in record recordName";
2291 # is_option_set checks if an option is set in a given record in given problem.
2293 my ( @problems, @records, @options );
2294 my $accessor = $record.'s';
2295 if ( defined $self -> {'problems'} ) {
2296 @problems = @
{$self -> {'problems'}};
2298 'debug' -> die( message
=> "No problems defined in model" );
2300 unless( defined $problems[$problem_number - 1] ){
2301 'debug' -> warn( level
=> 2,
2302 message
=> "model -> is_option_set: No problem number $problem_number defined in model" );
2303 return 0; # No option can be set if no problem exists.
2306 if ( defined $problems[$problem_number - 1] -> $accessor ) {
2307 @records = @
{$problems[$problem_number - 1] -> $accessor};
2309 'debug' -> warn( level
=> 2,
2310 message
=> "model -> is_option_set: No record $record defined" .
2311 " in problem number $problem_number." );
2315 unless(defined $records[$instance - 1] ){
2316 'debug' -> warn( level
=> 2,
2317 message
=> "model -> is_option_set: No record instance number $instance defined in model." );
2321 if ( defined $records[$instance - 1] -> options
) {
2322 @options = @
{$records[$instance - 1] -> options
};
2324 'debug' -> warn( level
=> 2,
2325 message
=> "No option defined in record: $record in problem number $problem_number." );
2328 foreach my $option ( @options ) {
2329 $found = 1 if ( defined $option and $option -> name
eq $name );
2345 my $fractions = $model_object -> fractions;
2361 =item problem_number
2365 =item return_occurences
2369 =item ignore_missing
2377 fractions will return the fractions from data::fractions. It will find
2378 "column_head" in the $INPUT record instead of that data header as
2379 data::fractions does.
2387 # is_run returns true if the outputobject owned by the
2388 # modelobject has valid outpudata either in memory or on disc.
2389 if( defined $self -> {'outputs'} ){
2390 if( @
{$self -> {'outputs'}}[0] -> have_output
){
2409 my $fractions = $model_object -> fractions;
2425 =item problem_number
2429 =item return_occurences
2433 =item ignore_missing
2441 fractions will return the fractions from data::fractions. It will find
2442 "column_head" in the $INPUT record instead of that data header as
2443 data::fractions does.
2449 my $problems = $self -> {'problems'};
2450 if( defined $problems -> [$problem_number - 1] ) {
2451 my $problem = $problems -> [$problem_number - 1];
2452 # If we don't have an ESTIMATION record we are simulating.
2453 $is_sim = 1 unless( defined $problem -> {'estimations'} and
2454 scalar( @
{$problem-> {'estimations'}} ) > 0 );
2456 # If we have a ONLYSIM option in the simulation record.
2457 $is_sim = 1 if( $self -> is_option_set
( name
=> 'ONLYSIM',
2458 record
=> 'simulation',
2459 problem_number
=> $problem_number ));
2461 # If max evaluations is zero we are simulating
2462 $is_sim = 1 if( defined $self -> maxeval
(problem_numbers
=> [$problem_number]) and
2463 defined $self -> maxeval
(problem_numbers
=> [$problem_number])->[0][0] and
2464 $self -> maxeval
(problem_numbers
=> [$problem_number])->[0][0] == 0 );
2468 # If non of the above is true, we are estimating.
2470 'debug' -> warn( level
=> 1,
2471 message
=> 'Problem nr. $problem_number not defined. Assuming no simulation' );
2487 my $fractions = $model_object -> fractions;
2503 =item problem_number
2507 =item return_occurences
2511 =item ignore_missing
2519 fractions will return the fractions from data::fractions. It will find
2520 "column_head" in the $INPUT record instead of that data header as
2521 data::fractions does.
2527 # lower_bounds either sets or gets the initial values of the
2528 # parameter specified in the argument parameter_type for
2529 # each problem specified in problem_numbers. See L</fixed>.
2531 @lower_bounds = @
{ $self -> _init_attr
2532 ( parameter_type
=> $parameter_type,
2533 parameter_numbers
=> \
@parameter_numbers,
2534 problem_numbers
=> \
@problem_numbers,
2535 new_values
=> \
@new_values,
2536 attribute
=> 'lobnd')};
2550 my $fractions = $model_object -> fractions;
2566 =item problem_number
2570 =item return_occurences
2574 =item ignore_missing
2582 fractions will return the fractions from data::fractions. It will find
2583 "column_head" in the $INPUT record instead of that data header as
2584 data::fractions does.
2592 # @labels = @{$modobj -> labels( parameter_type => 'theta' )};
2594 # This basic usage takes one arguments and returns matched names and
2595 # estimated values of the specified parameter. The parameter_type argument
2596 # is mandatory. It returns the labels of all parameters of type given by
2598 # @labels will be a two-dimensional array:
2599 # [[label1][label2][label3]...]
2601 # $labels -> labels( parameter_type => 'theta',
2602 # problem_numbers => [2,4] );
2604 # To get labels of specific problems, the problem_numbers argument can be used.
2605 # It should be a reference to an array containing the numbers
2606 # of all problems whos labels should be retrieved.
2608 # $modobj -> labels( parameter_type => 'theta',
2609 # problem_numbers => [2,4],
2610 # parameter_numbers => [[1,3][4,6]]);
2612 # The retrieval can be even more specific by using the parameter_numbers
2613 # argument. It should be a reference to a two-dimensional array, where
2614 # the inner arrays holds the numbers of the parameters that should be
2615 # fetched. In the example above, parameters one and three from problem two
2616 # plus parameters four and six from problem four are retrieved.
2618 # $modobj -> labels( parameter_type => 'theta',
2619 # problem_numbers => [2,4],
2620 # parameter_numbers => [[1,3][4,6]],
2623 # To get generic labels for the parameters - e.g. OM1, OM2_1, OM2 etc -
2624 # set the generic argument to 1.
2626 # $modobj -> labels( parameter_type => 'theta',
2627 # problem_numbers => [2],
2628 # parameter_numbers => [[1,3]],
2629 # new_values => [['Volume','Clearance']] );
2631 # The new_values argument can be used to give parameters new labels. In
2632 # the above example, parameters one and three in problem two are renamed
2633 # Volume and Clearance.
2636 my ( @index, $idx );
2637 @labels = @
{ $self -> _init_attr
2638 ( parameter_type
=> $parameter_type,
2639 parameter_numbers
=> \
@parameter_numbers,
2640 problem_numbers
=> \
@problem_numbers,
2641 new_values
=> \
@new_values,
2642 attribute
=> 'label' )};
2644 # foreach my $prl ( @labels ) {
2645 # foreach my $label ( @{$prl} ) {
2646 # print "Label: $label\n";
2651 @index = @
{$self -> indexes
( parameter_type
=> $parameter_type,
2652 parameter_numbers
=> \
@parameter_numbers,
2653 problem_numbers
=> \
@problem_numbers )};
2654 for ( my $i = 0; $i <= $#labels; $i++ ) {
2655 for ( my $j = 0; $j < scalar @
{$labels[$i]}; $j++ ) {
2656 $idx = $index[$i][$j];
2657 $labels[$i][$j] = uc(substr($parameter_type,0,2)).$idx
2658 unless ( defined $labels[$i][$j] and not $generic );
2674 my $fractions = $model_object -> fractions;
2690 =item problem_number
2694 =item return_occurences
2698 =item ignore_missing
2706 fractions will return the fractions from data::fractions. It will find
2707 "column_head" in the $INPUT record instead of that data header as
2708 data::fractions does.
2716 # @maxev = @{$modobj -> maxeval};
2718 # This basic usage takes no arguments and returns the value of the
2719 # MAXEVAL option in the $ESTIMATION record of each problem.
2720 # @maxev will be a two dimensional array:
2721 # [[maxeval_prob1][maxeval_prob2][maxeval_prob3]...]
2723 # $modobj -> maxeval( new_values => [[0],[999]];
2725 # If the new_values argument of maxeval is given, the values of the
2726 # MAXEVAL options will be changed. In this example, MAXEVAL will be
2727 # set to 0 in the first problem and to 999 in the second.
2728 # The number of elements in new_values must match the number of problems
2729 # in the model object $modobj.
2731 # $modobj -> maxeval( new_values => [[0],[999]],
2732 # problem_numbers => [2,4] );
2734 # To set the MAXEVAL of specific problems, the problem_numbers argument can
2735 # be used. It should be a reference to an array containing the numbers
2736 # of all problems where the MAXEVAL should be changed or retrieved.
2737 # If specified, the size of new_values must be the same as the size
2738 # of problem_numbers.
2743 my ( $val_ref, $junk ) = $self ->
2744 _option_val_pos
( name
=> 'MAX',
2745 record_name
=> 'estimation',
2746 problem_numbers
=> \
@problem_numbers,
2747 new_values
=> \
@new_values,
2748 exact_match
=> $exact_match );
2749 @values = @
{$val_ref};
2763 my $fractions = $model_object -> fractions;
2779 =item problem_number
2783 =item return_occurences
2787 =item ignore_missing
2795 fractions will return the fractions from data::fractions. It will find
2796 "column_head" in the $INPUT record instead of that data header as
2797 data::fractions does.
2803 # Calls <I>median</I> on the data object of a specified
2804 # problem. See <I>data -> median</I> for details.
2806 my $extra_data_column;
2807 if ( defined $column_head ) {
2808 # Check normal data object first
2809 my ( $values_ref, $positions_ref ) = $self ->
2810 _get_option_val_pos
( problem_numbers
=> [$problem_number],
2811 name
=> $column_head,
2812 record_name
=> 'input',
2813 global_position
=> 1 );
2814 $column_number = $positions_ref -> [0];
2815 if ( not defined $column_number ) {
2816 # Next, check extra_data
2817 my $extra_data_headers = $self -> extra_data_headers
;
2818 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
2819 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
2820 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
2824 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
2825 unless ( defined $column_number or defined $extra_data_column );
2827 $column_number = $column;
2830 if ( defined $column_number) {
2831 $median = $self -> {'datas'} -> [$problem_number-1] ->
2832 median
( column
=> $column_number,
2833 unique_in_individual
=> $unique_in_individual );
2835 $median = $self -> {'problems'} -> [$problem_number-1] -> extra_data
->
2836 median
( column
=> $extra_data_column,
2837 unique_in_individual
=> $unique_in_individual );
2852 my $fractions = $model_object -> fractions;
2868 =item problem_number
2872 =item return_occurences
2876 =item ignore_missing
2884 fractions will return the fractions from data::fractions. It will find
2885 "column_head" in the $INPUT record instead of that data header as
2886 data::fractions does.
2892 # Calls <I>max</I> on the data object of a specified
2893 # problem. See <I>data -> max</I> for details.
2895 my $extra_data_column;
2896 if ( defined $column_head ) {
2897 # Check normal data object first
2898 my ( $values_ref, $positions_ref ) = $self ->
2899 _get_option_val_pos
( problem_numbers
=> [$problem_number],
2900 name
=> $column_head,
2901 record_name
=> 'input',
2902 global_position
=> 1 );
2903 $column_number = $positions_ref -> [0];
2904 if ( not defined $column_number ) {
2905 # Next, check extra_data
2906 my $extra_data_headers = $self -> extra_data_headers
;
2907 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
2908 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
2909 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
2913 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
2914 unless ( defined $column_number or defined $extra_data_column );
2916 $column_number = $column;
2919 if ( defined $column_number) {
2920 $max = $self -> {'datas'} -> [$problem_number-1] ->
2921 max
( column
=> $column_number );
2923 $max = $self -> {'problems'} -> [$problem_number-1] -> extra_data
->
2924 max
( column
=> $extra_data_column );
2939 my $fractions = $model_object -> fractions;
2955 =item problem_number
2959 =item return_occurences
2963 =item ignore_missing
2971 fractions will return the fractions from data::fractions. It will find
2972 "column_head" in the $INPUT record instead of that data header as
2973 data::fractions does.
2979 # Calls <I>min</I> on the data object of a specified
2980 # problem. See <I>data -> min</I> for details.
2982 my $extra_data_column;
2983 if ( defined $column_head ) {
2984 # Check normal data object first
2985 my ( $values_ref, $positions_ref ) = $self ->
2986 _get_option_val_pos
( problem_numbers
=> [$problem_number],
2987 name
=> $column_head,
2988 record_name
=> 'input',
2989 global_position
=> 1 );
2990 $column_number = $positions_ref -> [0];
2991 if ( not defined $column_number ) {
2992 # Next, check extra_data
2993 my $extra_data_headers = $self -> extra_data_headers
;
2994 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
2995 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
2996 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
3000 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
3001 unless ( defined $column_number or defined $extra_data_column );
3003 $column_number = $column;
3006 if ( defined $column_number) {
3007 $min = $self -> {'datas'} -> [$problem_number-1] ->
3008 min
( column
=> $column_number );
3010 $min = $self -> {'problems'} -> [$problem_number-1] -> extra_data
->
3011 min
( column
=> $extra_data_column );
3027 my $fractions = $model_object -> fractions;
3043 =item problem_number
3047 =item return_occurences
3051 =item ignore_missing
3059 fractions will return the fractions from data::fractions. It will find
3060 "column_head" in the $INPUT record instead of that data header as
3061 data::fractions does.
3069 # @name_val = @{$modobj -> name_val( parameter_type => 'theta' )};
3071 # This basic usage takes one arguments and returns matched names and
3072 # estimated values of the specified parameter. The parameter_type argument
3074 # The names are taken from
3075 # the labels of the parameters (se the labels method for specifications of
3076 # default labels) and the values are aquired from the output object bound
3077 # to the model object. If no output exists, the name_val method returns
3079 # @name_val will be a two-dimensional array of references to hashes using
3080 # the names from each problem as keys:
3081 # [[ref to hash1 ][ref to hash2][ref to hash3]...]
3083 # $modobj -> name_val( parameter_type => 'theta',
3084 # problem_numbers => [2,4] );
3086 # To get matched names and values of specific problems, the problem_numbers argument
3087 # can be used. It should be a reference to an array containing the numbers
3088 # of all problems whos names and values should be retrieved.
3090 # $modobj -> name_val( parameter_type => 'theta',
3091 # problem_numbers => [2,4],
3092 # parameter_numbers => [[1,3][4,6]]);
3094 # The retrieval can be even more specific by using the parameter_numbers
3095 # argument. It should be a reference to a two-dimensional array, where
3096 # the inner arrays holds the numbers of the parameters that should be
3097 # fetched. In the example above, parameters one and three from problem two
3098 # plus parameters four and six from problem four are retrieved.
3101 unless( $#problem_numbers > 0 ){
3102 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
3104 my @names = @
{$self -> labels
( parameter_type
=> $parameter_type,
3105 parameter_numbers
=> \
@parameter_numbers,
3106 problem_numbers
=> \
@problem_numbers )};
3108 if ( defined $self -> outputs
-> [0] ) {
3109 my $accessor = $parameter_type.'s';
3110 @values = @
{$self -> outputs
-> [0] ->
3111 $accessor( problems
=> \
@problem_numbers,
3112 parameter_numbers
=> \
@parameter_numbers )};
3113 # my @problems = @{$self -> {'problems'}};
3114 # foreach my $i ( @problem_numbers ) {
3115 # if ( defined $problems[ $i-1 ] ) {
3116 # my $pn_ref = $#parameter_numbers >= 0 ? \@{$parameter_numbers[ $i-1 ]} : [];
3117 # push( @names_values,
3118 # $problems[ $i-1 ] ->
3119 # name_val( parameter_type => $parameter_type,
3120 # parameter_numbers => $pn_ref ) );
3122 # die "Model -> name_val: Problem number $i does not exist!\n";
3126 # if ( scalar @{$self -> {'outputs'}} > 0 ) {
3127 # my $outobj = $self -> {'outputs'} -> [0];
3130 'debug' -> die( message
=> "The number of problems retrieved from the model" .
3131 " do not match the ones retrived from the output" ) unless( $#names == $#values );
3132 for( my $i = 0; $i <= $#names; $i++ ) {
3133 'debug' -> die( message
=> "Problem " . $i+1 .
3134 " The number of parameters retrieved from the model (".scalar @
{$names[$i]}.
3135 ") do not match the ones retrived from the output (".
3136 scalar @
{$values[$i][0]}.")" )
3137 unless( scalar @
{$names[$i]} == scalar @
{$values[$i][0]} );
3139 for( my $j = 0; $j < scalar @
{$values[$i]}; $j++ ){
3141 for( my $k = 0; $k < scalar @
{$names[$i]}; $k++ ){
3142 $nv{$names[$i][$k]} = $values[$i][$j][$k];
3144 push( @prob_nv, \
%nv );
3146 push( @names_values, \
@prob_nv );
3161 my $fractions = $model_object -> fractions;
3177 =item problem_number
3181 =item return_occurences
3185 =item ignore_missing
3193 fractions will return the fractions from data::fractions. It will find
3194 "column_head" in the $INPUT record instead of that data header as
3195 data::fractions does.
3201 # nproblems returns the number of problems in the modelobject.
3203 $number_of_problem = scalar @
{$self -> {'problems'}};
3217 my $fractions = $model_object -> fractions;
3233 =item problem_number
3237 =item return_occurences
3241 =item ignore_missing
3249 fractions will return the fractions from data::fractions. It will find
3250 "column_head" in the $INPUT record instead of that data header as
3251 data::fractions does.
3257 # returns the number of thetas in the model for the given
3259 $nthetas = $self -> _parameter_count
( 'record' => 'theta', 'problem_number' => $problem_number );
3273 my $fractions = $model_object -> fractions;
3289 =item problem_number
3293 =item return_occurences
3297 =item ignore_missing
3305 fractions will return the fractions from data::fractions. It will find
3306 "column_head" in the $INPUT record instead of that data header as
3307 data::fractions does.
3313 # returns the number of omegas in the model for the given
3315 # $nomegas = $self -> _parameter_count( 'record' => 'omega', 'problem_number' => $problem_number );
3316 unless( $#problem_numbers >= 0 ){
3317 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
3320 my @problems = @
{$self -> {'problems'}};
3321 foreach my $i ( @problem_numbers ) {
3322 if ( defined $problems[ $i-1 ] ) {
3323 push( @nomegas, $problems[ $i-1 ] -> nomegas
);
3325 'debug' -> die( "Problem number $i does not exist." );
3341 my $fractions = $model_object -> fractions;
3357 =item problem_number
3361 =item return_occurences
3365 =item ignore_missing
3373 fractions will return the fractions from data::fractions. It will find
3374 "column_head" in the $INPUT record instead of that data header as
3375 data::fractions does.
3381 # returns the number of sigmas in the model for the given problem number.
3383 # $nsigmas = $self -> _parameter_count( 'record' => 'sigma', 'problem_number' => $problem_number );
3385 unless( $#problem_numbers >= 0 ){
3386 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
3389 my @problems = @
{$self -> {'problems'}};
3390 foreach my $i ( @problem_numbers ) {
3391 if ( defined $problems[ $i-1 ] ) {
3392 push( @nsigmas, $problems[ $i-1 ] -> nsigmas
);
3394 'debug' -> die( "Problem number $i does not exist." );
3410 my $fractions = $model_object -> fractions;
3426 =item problem_number
3430 =item return_occurences
3434 =item ignore_missing
3442 fractions will return the fractions from data::fractions. It will find
3443 "column_head" in the $INPUT record instead of that data header as
3444 data::fractions does.
3452 # This method is a (partially) automatically generated accessor for the
3453 # outputfile attribute of the model class. Since no named argument is needed
3454 # for accessors, the two possible ways of calling outputfile are:
3456 # $modelObject -> outputfile( 'newfilename.lst' );
3458 # $outputfilename = $modelObject -> outputfile;
3460 # The first alternative sets a new name for the output file, and the second
3461 # retrieves the value.
3463 # The extra feature for this accessor, compared to other accessors, is that
3464 # if a new name is given, the accessor tries to create a new output object
3467 if( defined $parm ) {
3468 $self -> {'outputs'} =
3470 new
( filename
=> $parm,
3471 ignore_missing_files
=> $self -> {'ignore_missing_files'},
3472 target
=> $self -> {'target'},
3473 model_id
=> $self -> {'model_id'} ) ];
3488 my $fractions = $model_object -> fractions;
3504 =item problem_number
3508 =item return_occurences
3512 =item ignore_missing
3520 fractions will return the fractions from data::fractions. It will find
3521 "column_head" in the $INPUT record instead of that data header as
3522 data::fractions does.
3528 # sets or gets the pk code for a given problem in the
3529 # model object. The new_pk argument should be an array where
3530 # each element contains a row of a valid NONMEM $PK block,
3532 my @prob = @
{$self -> problems
};
3534 unless( defined $prob[$problem_number - 1] ){
3535 'debug' -> die( message
=> "Problem number $problem_number does not exist" );
3538 my $pks = $prob[$problem_number - 1] -> pks
;
3539 if( scalar @new_pk > 0 ) {
3540 if( defined $pks and scalar @
{$pks} > 0 ){
3541 $prob[$problem_number - 1] -> pks
-> [0] -> code
(\
@new_pk);
3543 'debug' -> die( message
=> "No \$PK record" );
3546 if ( defined $pks and scalar @
{$pks} > 0 ) {
3547 @pk = @
{$prob[$problem_number - 1] -> pks
-> [0] -> code
};
3563 my $fractions = $model_object -> fractions;
3579 =item problem_number
3583 =item return_occurences
3587 =item ignore_missing
3595 fractions will return the fractions from data::fractions. It will find
3596 "column_head" in the $INPUT record instead of that data header as
3597 data::fractions does.
3603 # Sets or gets the pred code for a given problem in the model
3604 # object. See L</pk> for details.
3605 my @prob = @
{$self -> problems
};
3607 unless( defined $prob[$problem_number - 1] ){
3608 'debug' -> die( message
=> "problem number $problem_number does not exist" );
3611 if( scalar @new_pred > 0 ) {
3612 if( defined $prob[$problem_number - 1] -> preds
){
3613 $prob[$problem_number - 1] -> preds
-> [0] -> code
(\
@new_pred);
3615 'debug' -> die( message
=> "No \$PRED record" );
3618 if ( defined $prob[$problem_number - 1] -> preds
) {
3619 @pred = @
{$prob[$problem_number - 1] -> preds
-> [0] -> code
};
3621 'debug' -> die( message
=> "No \$PRED record" );
3637 my $fractions = $model_object -> fractions;
3653 =item problem_number
3657 =item return_occurences
3661 =item ignore_missing
3669 fractions will return the fractions from data::fractions. It will find
3670 "column_head" in the $INPUT record instead of that data header as
3671 data::fractions does.
3677 # Prints the formatted model to standard out.
3680 foreach my $problem ( @
{$self -> {'problems'}} ) {
3681 push( @formatted, $problem -> format_problem
);
3683 for ( @formatted ) {
3691 # {{{ problem_structure
3693 start problem_structure
3695 my ( $val, $pos ) = $self -> _option_val_pos
( record_name
=> 'simulation',
3696 name
=> 'SUBPROBLEMS' );
3697 if( defined $val ) {
3699 for( my $i = 0; $i <= $#vals; $i++ ) {
3700 if( defined $vals[$i] ) {
3701 if( scalar @
{$vals[$i]} > 0 ) {
3702 $subproblems[$i] = $vals[$i][0];
3704 $subproblems[$i] = 1;
3707 $subproblems[$i] = 1;
3712 end problem_structure
3714 # }}} problem_structure
3716 # {{{ randomize_inits
3724 my $fractions = $model_object -> fractions;
3740 =item problem_number
3744 =item return_occurences
3748 =item ignore_missing
3756 fractions will return the fractions from data::fractions. It will find
3757 "column_head" in the $INPUT record instead of that data header as
3758 data::fractions does.
3762 start randomize_inits
3764 foreach my $prob ( @
{$self -> {'problems'}} ) {
3765 $prob -> set_random_inits
( degree
=> $degree );
3781 my $fractions = $model_object -> fractions;
3797 =item problem_number
3801 =item return_occurences
3805 =item ignore_missing
3813 fractions will return the fractions from data::fractions. It will find
3814 "column_head" in the $INPUT record instead of that data header as
3815 data::fractions does.
3821 # If the argument new_data is given, record sets new_data in
3822 # the model objects member specified with record_name. The
3823 # format of new_data is an array of strings, where each
3824 # element corresponds to a line of code as it would have
3825 # looked like in a valid NONMEM modelfile. If new_data is left
3826 # undefined, record returns lines of code belonging to the
3827 # record specified by record_name in a format that is valid in
3828 # a NONMEM modelfile.
3830 my @problems = @
{$self -> {'problems'}};
3833 if ( defined $problems[ $problem_number - 1 ] ) {
3834 if ( scalar(@new_data) > 0 ){
3835 my $rec_class = "model::problem::$record_name";
3836 my $record = $rec_class -> new
('record_arr' => \
@new_data );
3838 $record_name .= 's';
3839 $records = $problems[ $problem_number - 1 ] -> {$record_name};
3840 foreach my $record( @
{$records} ){
3841 push(@data, $record -> _format_record
);
3858 my $fractions = $model_object -> fractions;
3874 =item problem_number
3878 =item return_occurences
3882 =item ignore_missing
3890 fractions will return the fractions from data::fractions. It will find
3891 "column_head" in the $INPUT record instead of that data header as
3892 data::fractions does.
3900 # $model -> remove_inits( type => 'theta',
3901 # indexes => [1,2,5,6] )
3904 # In all cases the type must be set to theta. Removing Omegas in
3905 # Sigmas is not allowed, (If need that feature, send us a
3906 # mail). In the above example the thetas 1, 2, 5 and 6 will be
3907 # removed from the modelfile. Notice that this alters the theta
3908 # numbering, so if you later decide that theta number 7 must be
3909 # removed as well, you must calculate its new position in the
3910 # file. In this case the new number would be 3. Also notice that
3911 # numbering starts with 1.
3913 # $model -> remove_inits( type => 'theta',
3914 # labels => ['V', 'CL'] )
3917 # If you have specified labels in you modelfiles(a label is
3918 # string inside a comment on the same row as the theta) you can
3919 # specify an array with labels, and the corresponding theta, if
3920 # it exists, will be removed. This is a much better approach
3921 # since you don't need to know where in order the theta you wish
3922 # to remove appears. If you specify both labels and indexes, the
3923 # indexes will be ignored.
3925 'debug' -> die( message
=> 'does not have the functionality for removing $OMEGA or $SIGMA options yet' )
3926 if ( $type eq 'omega' or $type eq 'sigma' );
3927 my $accessor = $type.'s';
3929 # First pick out a referens to the theta records array.
3930 my $inits_ref = $self -> problems
-> [$problem_number -1] -> $accessor;
3932 # If we have any thetas at all:
3933 if ( defined $inits_ref ) {
3934 my @inits = @
{$inits_ref};
3936 # If labels are specified, we translate the labels into
3938 if ( scalar @labels > 0 ) {
3941 # Loop over theta records
3942 foreach my $init ( @inits ) {
3943 # Loop over the individual thetas inside
3944 foreach my $option ( @
{$init -> options
} ) {
3945 # Loop over all given labels.
3946 foreach my $label ( @labels ) {
3947 # Push the index number if a given label match the
3949 push( @indexes, $i ) if ( $option -> label
eq $label);
3951 # $i is the count of thetas so far
3957 # We don't really remove thetas, we do a loop over all thetas
3958 # and recording which we like to keep. We do that by selecting
3959 # an index, from @indexes, that shall be removed and loop over
3960 # the thetas, all thetas that doesn't match the index are
3961 # stored in @keep_options. When we find a theta that matches,
3962 # we pick a new index and continue the loop. So by makeing
3963 # sure that @indexes is sorted, we only need to loop over the
3966 @indexes = sort {$a <=> $b} @indexes;
3972 # Loop over all records
3973 RECORD_LOOP
: foreach my $record ( @inits ){
3974 my @keep_options = ();
3975 # Loop over all thetas
3976 foreach my $option ( @
{$record -> options
} ) {
3977 if( $indexes[ $index ] == $nr_options ){
3978 # If a theta matches an index, we take the next index
3979 # and forget the theta.
3980 unless( $index > $#indexes ){
3984 # Otherwise we rember it.
3985 push(@keep_options,$option);
3989 if( scalar(@keep_options) > 0 ){
3990 # If we remember some thetas, we must also remember the
3991 # record which they are in.
3992 $record -> options
( \
@keep_options );
3993 push( @keep_records, $record );
3997 # Set the all kept thetas back into the modelobject.
3998 @
{$inits_ref} = @keep_records;
4001 'debug' -> die( message
=> "No init of type $type defined" );
4016 my $fractions = $model_object -> fractions;
4032 =item problem_number
4036 =item return_occurences
4040 =item ignore_missing
4048 fractions will return the fractions from data::fractions. It will find
4049 "column_head" in the $INPUT record instead of that data header as
4050 data::fractions does.
4056 # restore_inits brings back initial values previously stored
4057 # using store_inits. This method pair allows a user to store
4058 # the currents initial values in a backup, replace them with
4059 # temporary values and later restore them.
4061 if ( defined $self -> {'problems'} ) {
4062 foreach my $problem ( @
{$self -> {'problems'}} ){
4063 $problem -> restore_inits
;
4079 my $fractions = $model_object -> fractions;
4095 =item problem_number
4099 =item return_occurences
4103 =item ignore_missing
4111 fractions will return the fractions from data::fractions. It will find
4112 "column_head" in the $INPUT record instead of that data header as
4113 data::fractions does.
4119 # store_inits stores initial values that can later be
4120 # brought back using restore_inits. See L</restore_inits>.
4122 if ( defined $self -> {'problems'} ) {
4123 foreach my $problem ( @
{$self -> {'problems'}} ){
4124 $problem -> store_inits
;
4136 # Synchronize checks the I<synced> object attribute to see
4137 # if the model is in sync with its corresponding file, given
4138 # by the objetc attribute I<filename>. If not, it checks if
4139 # the model contains any defined problems and if it does, it
4140 # writes the formatted model to disk, overwriting any
4141 # existing file of name I<filename>. If no problem is
4142 # defined, synchronize tries to parse the file I<filename>
4143 # and set the object internals to match it.
4144 unless( $self -> {'synced'} ){
4145 if( defined $self -> {'problems'} and
4146 scalar @
{$self -> {'problems'}} > 0 ){
4149 if( -e
$self -> full_name
){
4150 $self -> _read_problems
;
4156 $self -> {'synced'} = 1;
4164 # synchronizes the object with the file on disk and empties
4165 # most of the objects attributes to save memory.
4166 if( defined $self -> {'problems'} and
4167 ( !$self -> {'synced'} or $force ) ) {
4170 $self -> {'problems'} = undef;
4171 $self -> {'synced'} = 0;
4179 if ( $parm eq 'disk' ) {
4180 $self -> {'target'} = 'disk';
4182 } elsif ( $parm eq 'mem' and $self -> {'target'} eq 'disk' ) {
4183 $self -> {'target'} = 'mem';
4184 $self -> synchronize
;
4198 my $fractions = $model_object -> fractions;
4214 =item problem_number
4218 =item return_occurences
4222 =item ignore_missing
4230 fractions will return the fractions from data::fractions. It will find
4231 "column_head" in the $INPUT record instead of that data header as
4232 data::fractions does.
4240 # @tableNames = @{$modobj -> table_names};
4242 # This basic usage takes no arguments and returns the value of
4243 # the FILE option in the $TABLE NONMEM record of each
4244 # problem. @tableNames will be a two dimensional array:
4246 # [[tableName_prob1][tableName_prob2][tableName_prob3]...]
4249 # If the I<new_names> argument of table_names is given, the
4250 # values of the FILE options will be changed.
4252 # To set the FILE of specific problems, the I<problem_numbers>
4253 # argument can be used. It should be a reference to an array
4254 # containing the numbers of all problems where the FILE should
4255 # be changed or retrieved. If specified, the size of
4256 # I<new_names> must be the same as the size of
4257 # I<problem_numbers>.
4259 # The I<ignore_missing_files> boolean argument can be used to
4260 # set names of table that does not exist yet (e.g. before a
4261 # run has been performed).
4263 my ( $name_ref, $junk ) = $self ->
4264 _option_val_pos
( name
=> 'FILE',
4265 record_name
=> 'table',
4266 problem_numbers
=> \
@problem_numbers,
4267 new_values
=> \
@new_names );
4268 if ( $#new_names >= 0 ) {
4269 my @problems = @
{$self -> {'problems'}};
4270 unless( $#problem_numbers > 0 ){
4271 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
4273 foreach my $i ( @problem_numbers ) {
4274 $problems[$i-1] -> _read_table_files
( ignore_missing_files
=> $ignore_missing_files || $self -> {'ignore_missing_output_files'});
4277 @names = @
{$name_ref};
4291 my $fractions = $model_object -> fractions;
4307 =item problem_number
4311 =item return_occurences
4315 =item ignore_missing
4323 fractions will return the fractions from data::fractions. It will find
4324 "column_head" in the $INPUT record instead of that data header as
4325 data::fractions does.
4333 # @table_files = @{$modobj -> table_files};
4335 # This basic usage takes no arguments and returns the table
4336 # files objects for all problems. @table_files will be a
4337 # two dimensional array:
4339 # [[table_file_object_prob1][table_file_object_prob2]...]
4342 # To retrieve the table file objects from specific problems,
4343 # the I<problem_numbers> argument can be used. It should be
4344 # a reference to an array containing the numbers of all
4345 # problems from which the table file objects should be
4348 unless( $#problem_numbers > 0 ){
4349 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
4351 my @problems = @
{$self -> {'problems'}};
4352 foreach my $i ( @problem_numbers ) {
4353 if ( defined $problems[ $i-1 ] ) {
4354 push( @table_files, $problems[$i-1] -> table_files
);
4356 'debug' -> die( message
=> "Problem number $i does not exist!" );
4372 my $fractions = $model_object -> fractions;
4388 =item problem_number
4392 =item return_occurences
4396 =item ignore_missing
4404 fractions will return the fractions from data::fractions. It will find
4405 "column_head" in the $INPUT record instead of that data header as
4406 data::fractions does.
4412 # Sets or gets the units of a (number of) parameter(s). The
4413 # unit is not a proper NONMEM syntax but is recognized by
4414 # the PsN model class. A unit (and a label) can be specified
4415 # as a comments after a parameter definition. e.g.:
4417 # $THETA (0,13.2,100) ; MTT; h
4419 # which will give this theta the label I<MTT> and unit I<h>.
4420 @units = @
{ $self -> _init_attr
( parameter_type
=> $parameter_type,
4421 parameter_numbers
=> \
@parameter_numbers,
4422 problem_numbers
=> \
@problem_numbers,
4423 new_values
=> \
@new_values,
4439 my $fractions = $model_object -> fractions;
4455 =item problem_number
4459 =item return_occurences
4463 =item ignore_missing
4471 fractions will return the fractions from data::fractions. It will find
4472 "column_head" in the $INPUT record instead of that data header as
4473 data::fractions does.
4481 # $modobj -> update_inits ( from_output => $outobj );
4485 # $modobj -> update_inits ( from_output_file => $outfile );
4487 # This basic usage takes the parameter estimates from the
4488 # output object I<$outobj> or from the output file I<$outfile>
4489 # and updates the initial estimates in the model object
4490 # I<$modobj>. The number of problems and parameters must be
4491 # the same in the model and output objects. If there exist
4492 # more than one subproblem per problem in the output object,
4493 # only the estimates from the first subproblem will be
4496 # $modobj -> update_inits ( from_output => $outobj,
4497 # ignore_missing_parameters => 1 );
4499 # If the ignore_missing_parameters argument is set to 1, the number of
4500 # parameters in the model and output objects do not need to match. The
4501 # parameters that exist in both objects are used for the update of the
4504 # $modobj -> update_inits ( from_output => $outobj,
4505 # from_model => $from_modobj );
4507 # If the from_model argument is given, update_inits tries to match the
4508 # parameter names (labels) given in $from_modobj and $modobj and
4509 # and thereafter updating the $modobj object. See L</units> and L</labels>.
4512 my ( %labels, @own_labels, @from_labels );
4513 'debug' -> die( message
=> "No output object defined and" .
4514 " no output object found through the model object specified." )
4515 unless ( ( defined $from_model and
4516 ( defined $from_model -> outputs
and
4517 defined @
{$from_model -> outputs
}[0] ) ) or
4518 defined $from_output or
4519 defined $from_output_file );
4520 if ( defined $from_output ) {
4521 'debug' -> warn( level
=> 2,
4522 message
=> "using output object ".
4523 "specified as argument\n" );
4524 } elsif ( defined $from_output_file ) {
4525 $from_output = output
-> new
( filename
=> $from_output_file );
4527 $from_output = @
{$from_model -> outputs
}[0];
4531 if( $update_thetas ){
4532 push( @params, 'theta' );
4534 if( $update_omegas ) {
4535 push( @params, 'omega' );
4537 if( $update_sigmas ) {
4538 push( @params, 'sigma' );
4541 foreach my $param ( @params ) {
4542 # Get own labels and from labels
4543 if ( defined $from_model ) {
4544 @own_labels = @
{$self -> labels
( parameter_type
=> $param )};
4546 @from_labels = @
{$from_model -> labels
( parameter_type
=> $param )};
4547 'debug' -> die( message
=> "The number of problems are not the same in from-model ".
4548 $from_model -> full_name
." (".
4549 ($#from_labels+1).")".
4550 " and the model to be updated ".
4551 $self -> full_name
." (".
4552 ($#own_labels+1).")" ) unless ( $#own_labels == $#from_labels );
4554 @own_labels = @
{$self -> labels
( parameter_type
=> $param,
4556 @from_labels = @
{$from_output -> labels
( parameter_type
=> $param )};
4557 'debug' -> die( message
=> "The number of problems are not the same in from-output ".
4558 $from_output -> full_name
." (".
4559 ($#from_labels+1).")".
4560 " and the model to be updated ".
4561 $self -> full_name
." (".
4562 ($#own_labels+1).")" ) unless ( $#own_labels == $#from_labels );
4565 # Loop over the problems:
4566 my $accessor = $param.'s';
4567 # Since initial estimates are specified on the problem level and not on
4568 # the subproblem level we use the estimates from the outputs first subproblem
4569 my @from_values = @
{$from_output -> $accessor ( subproblems
=> [1] )};
4570 # {{{ Omega and Sigma update section
4572 # The functionality that has been commented out because it
4573 # fails when omegas are zero. This functionality should be
4574 # moved to output::problem::subproblem (2005-02-09) TODO
4576 # if ($param eq 'omega' or $param eq 'sigma')
4578 # #print "FL: ", Dumper @from_labels;
4579 # #print "OL: ", Dumper @own_labels;
4580 # print "FV: $param Before " . Dumper(@from_values) . "\n";
4581 # #Fix omegas and sigmas so that the correlation between elements <=1
4582 # my $raw_accessor = "raw_" . $accessor;
4583 # my @raw_from_values = @{$from_output -> $raw_accessor(subproblems => [1])};
4585 # for (my $a=0; $a<scalar(@from_values); $a++)
4587 # my $prob_values = $from_values[$a];
4588 # my $raw_prob_values = $raw_from_values[$a];
4589 # for (my $b=0; $b<scalar(@{$prob_values}); $b++)
4591 # my $values = $prob_values->[$b];
4592 # my $raw_values = $raw_prob_values->[$b];
4594 # #Find out the n*n-matrix size (pq-formula)
4595 # my $n = int(sqrt(1/4+scalar(@{$raw_values})*2)-1/2);
4596 # for ($i=0; $i<$n; $i++)
4598 # for ($j=0; $j<$n; $j++)
4600 # if ( $j<=$i && $raw_values->[$i*($i+1)/2+$j]!=0 )
4602 # #print "Omega value = " . @other_val[$counter] . "\n";
4605 # #Only check the low-triangular off-diagonals of the omega matrix
4606 # #omega(i,j)>=sqrt(omega(i,i)*omega(j,j))
4607 # if ($j<=$i && $j!=$i &&
4608 # ($raw_values->[$i*($i+1)/2+$j]>=sqrt(
4609 # $raw_values->[$i*($i+1)/2+$i]*$raw_values->[$j*($j+1)/2+$j])))
4611 # print "Changing raw value at $i, $j: " . $raw_values->[$i*($i+1)/2+$j] ." to ".
4612 # (int(10000*sqrt($raw_values->[$i*($i+1)/2+$i]*$raw_values->[$j*($j+1)/2+$j]))/10000) ."\n";
4613 # #print "At index ($i,$j)\n" if ($self->{'debug'});
4614 # $raw_values->[$i*($i+1)/2+$j]=int(10000*sqrt(
4615 # $raw_values->[$i*($i+1)/2+$i]*$raw_values->[$j*($j+1)/2+$j]))/10000;
4616 # print "Changing omega value " . $values->[$counter-1] . " to " . $raw_values->[$i*($i+1)/2+$j] ."\n";
4617 # $values->[$counter-1] = $raw_values->[$i*($i+1)/2+$j];
4623 # #print "FL: ", Dumper @from_labels;
4624 # #print "OL: ", Dumper @own_labels;
4625 # print "FV: $param After ", Dumper(@from_values), "\n";
4631 for ( my $i = 0; $i <= $#own_labels; $i++ ) {
4632 unless ( $ignore_missing_parameters ) {
4633 my $from_name = defined $from_model ?
$from_model -> filename
:
4634 $from_output -> filename
;
4635 'debug' -> die( message
=> "Model -> update_inits: The number of ".$param.
4636 "s are not the same in from-model (" . $from_name .
4637 "): " . scalar @
{$from_labels[$i]} .
4638 ", and the model to be updated (" . $self -> {'filename'} .
4639 "): " . scalar @
{$own_labels[$i]} )
4640 unless ( scalar @
{$own_labels[$i]} ==
4641 scalar @
{$from_labels[$i]} );
4644 for ( my $j = 0; $j < scalar @
{$from_labels[$i]}; $j++ ) {
4645 for ( my $k = 0; $k < scalar @
{$own_labels[$i]}; $k++ ) {
4646 if ( $from_labels[$i][$j] eq $own_labels[$i][$k] ){
4647 $labels{$k+1} = $from_values[$i][0][$j];
4652 my @own_idxs = keys( %labels );
4654 for(my $i=0; $i <= $#own_idxs; $i++){
4655 @from_vals[$i] = $labels{ $own_idxs[$i] };
4658 $self -> initial_values
( problem_numbers
=> [$i+1],
4659 parameter_type
=> $param,
4660 parameter_numbers
=> [\
@own_idxs],
4661 new_values
=> [\
@from_vals] );
4673 # upper_bounds either sets or gets the initial values of the
4674 # parameter specified in I<parameter_type> for each
4675 # subproblem specified in I<problem_numbers>. For each
4676 # element in I<problem_numbers> there must be an array in
4677 # I<parameter_numbers> that specify the indices of the
4678 # parameters in the subproblem for which the upper bounds
4679 # are set, replaced or retrieved.
4681 @upper_bounds = @
{ $self -> _init_attr
4682 ( parameter_type
=> $parameter_type,
4683 parameter_numbers
=> \
@parameter_numbers,
4684 problem_numbers
=> \
@problem_numbers,
4685 new_values
=> \
@new_values,
4686 attribute
=> 'upbnd')};
4692 # {{{ clean_extra_data_code
4693 start clean_extra_data_code
4696 # This method cleans out old code for extra data. It searches
4697 # all subroutine statements in all problems for external
4698 # subroutines named "get_sub" and "reader" which are added by
4699 # "add_extra_data_code".
4701 foreach my $problem( @
{$self -> {'problems'}} ){
4702 if ( defined $problem -> subroutines
and defined $problem -> subroutines
-> [0] -> options
) {
4703 foreach my $option ( @
{$problem -> subroutines
-> [0] -> options
} ){
4704 if( lc($option -> name
) eq 'other'){
4705 if( lc($option -> value
) =~ /get_sub|reader/ ){
4707 # If we find "get_sub" or "reader" we remove
4708 # everything between "IMPORTING COVARIATE DATA" and
4709 # "IMPORTING COVARIATE DATA END" by finding the
4710 # indexes in the code array and and splicing it out.
4713 if( $problem -> pks
){
4714 # If the code is in a pk block:
4715 $code = $problem -> pks
-> [0] -> code
;
4717 $code = $problem -> preds
-> [0] -> code
;
4722 for( my $i = 0; $i <= $#{$code}; $i++ ){
4723 if( $code -> [$i] eq ";***IMPORTING COVARIATE DATA*******\n" ){
4726 if( $code -> [$i] eq ";***IMPORTING COVARIATE DATA END***\n" ){
4730 @
{$code} = ( @
{$code}[0..$start_idx] , @
{$code}[$end_idx..$#{$code}] );
4732 if( $problem -> pks
){
4733 # Put the cut down code back in the right place:
4734 $problem -> pks
-> [0] -> code
( $code );
4736 $problem -> preds
-> [0] -> code
( $code );
4746 end clean_extra_data_code
4747 # }}} clean_extra_data_code
4749 # {{{ add_extra_data_code
4751 start add_extra_data_code
4753 # This method adds fortran code that will handle wide datasets
4754 # (that is data sets with more than 20 columns). It adds code to
4755 # each problems pk or pred.
4759 # Get the headers of the columns that have been moved to another
4762 # unless( defined $self -> extra_data_headers ){
4763 # die "ERROR model::add_extra_data_code: No headers for the extra data file\n";
4766 # extra_data_headers is a two dimensional array. One array of
4767 # headers for each problem in the modelfile.
4768 for( my $i = 0; $i <= $#{$self -> {'problems'}}; $i++ ){
4769 if ( defined $self -> {'problems'} -> [$i] -> {'extra_data_header'} ) {
4770 my $problem_headers = $self -> {'problems'} -> [$i] -> {'extra_data_header'};
4775 # Loop over the problem specific headers and make a string
4776 # that will go into the fortran code. Assume that the
4777 # first column holds the ID, hence the $i=1
4778 for (my $i = 1; $i <= $#{$problem_headers}; $i++ ) {
4779 my $header = $problem_headers -> [$i];
4780 push( @headers, $header );
4781 # Chopp the string at 40 characters, to be nice to g77 :)
4782 if ( $length + length($header) > 40 ) {
4783 $header_string .= "\n\"& ";
4786 if ( $i < $#{$problem_headers} ) {
4787 $header_string .= 'I' . $header . ', ';
4788 $length += length( 'I' . $header . ', ' );
4790 $header_string .= 'I' . $header;
4791 $length += length( 'I' . $header );
4795 my @code_lines = ('',
4796 ';***IMPORTING COVARIATE DATA*******',
4798 '" REAL CURID, MID,',
4799 '"& '.$header_string,
4802 '" IF (.NOT.READ) THEN',
4808 '" IF (NEWIND.LT.2) THEN',
4809 '" CALL GET_SUB (NEWIND,ID,CURID,MID,',
4810 '"& '.$header_string. ')',
4813 ' IF (CID.NE.ID) THEN',
4814 ' PRINT *, \'ERROR CHECKING FAILED, CID = \', CID ,\' ID = \', ID',
4818 foreach my $header ( @headers ) {
4819 push( @code_lines, " $header = I$header" );
4822 push( @code_lines, (';***IMPORTING COVARIATE DATA END***','','') );
4824 my $problem = $self -> {'problems'} -> [$i];
4825 if ( defined $problem -> {'subroutines'} ) {
4826 $problem -> subroutines
-> [0] -> _add_option
( option_string
=> 'OTHER=get_sub' . $i );
4827 $problem -> subroutines
-> [0] -> _add_option
( option_string
=> 'OTHER=reader' . $i );
4829 $problem -> add_records
( type
=> 'subroutines', record_strings
=> ['OTHER=get_sub', 'OTHER=reader'] );
4832 if ( defined $problem -> pks
) {
4833 unshift( @
{$problem -> pks
-> [0] -> code
}, join("\n", @code_lines ));
4835 unshift( @
{$problem -> preds
-> [0] -> code
},join("\n", @code_lines ));
4840 end add_extra_data_code
4848 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
4849 $self -> {'datas'}[$i] -> drop_dropped
( model_header
=> $self -> {'problems'}[$i] -> header
);
4850 $self -> {'problems'}[$i] -> drop_dropped
( );
4851 #$self -> {'datas'}[$i] -> model_header( $self -> {'problems'}[$i] -> header );
4862 my $default_wrap = 18;
4864 my ( @wrap_columns, @cont_columns );
4865 if ( not defined $wrap_column ) {
4866 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
4867 my $columns = scalar @
{$self -> {'problems'}[$i] -> dropped_columns
}-1; #skip ID
4868 my $modulus = $columns%($default_wrap-2); # default_wrap-2 to account for ID and CONT
4869 my $rows = (($columns-$modulus)/($default_wrap-2))+1;
4871 push( @wrap_columns, undef );
4873 push( @wrap_columns, (ceil
( $columns/$rows )+2) ); #Must use #cols + ID and CONT
4877 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
4878 push( @wrap_columns, $wrap_column );
4882 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
4883 next if ( not defined $wrap_columns[$i] );
4884 $wrap_column = $wrap_columns[$i];
4885 $cont_column = $wrap_columns[$i] if( not defined $cont_column );
4886 my ( $prim, $sec ) =
4887 $self -> {'datas'}[$i] -> wrap
( cont_column
=> $cont_column,
4888 wrap_column
=> $wrap_column,
4889 model_header
=> $self -> {'problems'}[$i] -> header
);
4890 $self -> {'problems'}[$i] -> primary_columns
( $prim );
4891 $self -> {'problems'}[$i] -> secondary_columns
( $sec );
4892 $self -> {'data_wrapped'}++;
4902 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
4903 $self -> {'datas'}[$i] -> unwrap
;
4904 $self -> {'problems'}[$i] -> primary_columns
( [] );
4905 $self -> {'problems'}[$i] -> secondary_columns
( [] );
4907 $self -> {'data_wrapped'} = 0;
4912 # {{{ write_get_subs
4914 start write_get_subs
4916 for( my $i = 0; $i <= $#{$self -> {'problems'}}; $i++ ){
4917 if ( defined $self -> {'problems'} -> [$i] -> {'extra_data_header'} and
4918 defined $self -> problems
-> [$i] -> extra_data
) {
4919 my @problem_header = @
{$self -> {'problems'} -> [$i] -> {'extra_data_header'}};
4924 my $rows = $self -> problems
-> [$i] -> extra_data
-> count_ind
;
4926 # Assume that first column holds the ID. Get rid of it.
4927 shift( @problem_header );
4928 for ( my $i = 0; $i <= $#problem_header; $i++ ) {
4929 my $header = $problem_header[$i];
4930 push( @headers, $header );
4931 # Chop the string at 40 characters, to be nice to g77 :)
4932 if ( $length + length($header) > 40 ) {
4933 $header_string .= "\n & ";
4936 if ( $i < $#problem_header ) {
4937 $header_string .= $header . ', ';
4938 $length += length( $header . ', ' );
4940 $header_string .= $header;
4941 $length += length( $header );
4945 open( FILE
, '>', 'get_sub' . $i . '.f' );
4946 print FILE
(" SUBROUTINE GET_SUB (NEWIND,ID,CURID,MID,\n",
4947 " & $header_string)\n",
4948 " COMMON /READ/ TID,TCOV\n",
4950 " REAL ID,CURID,MID,\n",
4951 " & $header_string\n",
4953 " INTEGER NEWIND\n",
4955 " REAL TID($rows), TCOV($rows,",scalar @problem_header,")\n",
4958 "C START AT TOP EVERY TIME\n",
4959 " IF (NEWIND.EQ.1) THEN \n",
4961 " IF (CURID.GT.$rows) THEN \n",
4962 " PRINT *, \"Covariate data not found for\", ID\n",
4967 " IF (ID.GT.TID (CURID)) THEN\n",
4968 " CURID = CURID + 1\n",
4971 " ELSEIF (NEWIND.EQ.0) THEN\n",
4976 for ( my $i = 1; $i <= $#headers+1; $i++ ) {
4977 $length += length("TCOV(I,$i),");
4978 if ( $length > 40 ) {
4982 print FILE
" ".$headers[$i-1] . " = TCOV(CURID,$i)\n";
4985 print FILE
(" MID = TID(CURID)\n",
5002 for( my $i = 0; $i <= $#{$self -> {'problems'}}; $i++ ){
5003 if ( defined $self -> {'problems'} -> [$i] -> {'extra_data_header'} and
5004 defined $self -> {'problems'} -> [$i] -> {'extra_data'} ) {
5005 my @problem_header = @
{$self -> {'problems'} -> [$i] -> {'extra_data_header'}};
5009 my $rows = $self -> problems
-> [$i] -> extra_data
-> count_ind
;
5010 my $filename = $self -> problems
-> [$i] -> extra_data
-> filename
;
5011 # Assume that first column holds the ID. Get rid of it.
5012 shift( @problem_header );
5014 'debug' -> warn( level
=> 2,
5015 message
=> "Writing reader".$i.".f to directory".cwd
);
5016 open( FILE
, '>', 'reader' . $i . '.f' );
5017 print FILE
(" SUBROUTINE READER()\n",
5019 " COMMON /READ/ TID,TCOV\n",
5021 " REAL TID ($rows), TCOV ($rows, ",scalar @problem_header,")\n",
5023 " OPEN (UNIT = 77,FILE = '$filename')\n",
5025 " DO 11,I = 1,$rows\n",
5026 " READ (77,*) TID(I)," );
5029 for ( my $i = 1; $i <= $#problem_header+1; $i++ ) {
5030 $length += length("TCOV(I,$i),");
5031 if ( $length > 40 ) {
5035 if ( $i <= $#problem_header ) {
5036 print FILE
"TCOV(I,$i),";
5038 print FILE
"TCOV(I,$i)\n";
5042 print FILE
( "11 CONTINUE\n",
5056 # $model -> _write( filename => 'model.mod' );
5058 # Writes the content of the modelobject to disk. Either to the
5059 # filename given, or to the string returned by model::full_name.
5063 # An element in the active_problems array is a boolean that
5064 # corresponds to the element with the same index in the problems
5065 # array. If the boolean is true, the problem will be run. All
5066 # other will be commented out.
5067 my @active = @
{$self -> {'active_problems'}};
5069 # loop over all problems.
5070 for ( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5071 # Call on the problem object to format it as text. The
5072 # filename and problem numbers are needed to make some
5073 # autogenerated files (msfi, tabels etc...) unique to the
5075 my @preformatted = @
{$self -> {'problems'} -> [$i] ->
5076 # _format_problem };
5077 _format_problem
( filename
=> $self -> filename
,
5078 problem_number
=> ($i+1) ) };
5079 # Check if the problem is NOT active, if so comment it out.
5080 unless ( $active[$i] ) {
5081 for ( my $j = 0; $j <= $#preformatted; $j++ ) {
5082 $preformatted[$j] = '; '.$preformatted[$j];
5085 # Add extra line to avoid problems with execution of NONMEM
5086 push(@preformatted,"\n");
5087 push( @formatted, @preformatted );
5090 # Open a file and print the formatted problems.
5091 # TODO Add some errorchecking.
5092 open( FILE
, '>'. $filename );
5093 for ( @formatted ) {
5100 if ( $write_data ) {
5101 foreach my $data ( @
{$self -> {'datas'}} ) {
5113 if ( defined $parm and $parm ne $self -> {'filename'} ) {
5114 $self -> {'filename'} = $parm;
5115 $self -> {'model_id'} = undef;
5122 # {{{ _get_option_val_pos
5124 start _get_option_val_pos
5128 # ( $values_ref, $positions_ref ) ->
5129 # _get_option_val_pos ( name => 'ID',
5130 # record_name => 'input' );
5131 # my @values = @{$values_ref};
5132 # my @positions = @{$positions_ref};
5134 # This basic usage returns the name of the third option in the first
5135 # instance of the record specified by I<record_name> for all problems
5137 # If global_position is set to 1, only one value and position
5138 # pair is returned per problem. If there are more than one
5139 # match in the model; the first will be returned for each
5142 # Private method, should preferably not be used outside model.pm
5144 # my ( @records, @instances );
5145 my $accessor = $record_name.'s';
5146 my @problems = @
{$self -> {'problems'}};
5147 unless( $#problem_numbers > 0 ){
5148 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5150 foreach my $i ( @problem_numbers ) {
5151 my $rec_ref = $problems[ $i-1 ] -> $accessor;
5152 if ( defined $problems[ $i-1 ] and defined $rec_ref ) {
5153 my @records = @
{$rec_ref};
5154 unless( $#instances > 0 ){
5155 @instances = (1 .. $#records+1);
5158 my @inst_values = ();
5159 my @inst_positions = ();
5161 my ( $glob_value, $glob_position );
5162 INSTANCES
: foreach my $j ( @instances ) {
5163 if ( defined $records[ $j-1 ] ) {
5165 my ( $value, $position );
5166 foreach my $option ( @
{$records[$j-1] -> {'options'}} ) {
5167 if ( defined $option and $option -> name
eq $name) {
5168 if ( $global_position ) {
5169 $glob_value = $option -> value
;
5170 $glob_position = $glob_pos;
5173 $value = $option -> value
;
5180 push( @inst_values, $value );
5181 push( @inst_positions, $position );
5183 'debug' -> die( message
=> "Instance $j in problem number $i does not exist!" )
5186 if ( $global_position ) {
5187 push( @values, $glob_value );
5188 push( @positions, $glob_position );
5190 push( @values, \
@inst_values );
5191 push( @positions, \
@inst_positions );
5194 'debug' -> die( message
=> "Problem number $i does not exist!" );
5197 # if( defined $problem_number ) {
5198 # if( $problem_number < 1 or $problem_number > scalar @problems ) {
5199 # die "model -> _get_option_val_pos: No such problem number, ",
5200 # $problem_number,", in this model!\n";
5204 # die "modelfile -> _get_option_val_pos: No problem $problem_number exists\n"
5205 # if( (scalar @problems < 1) and ($problem_number ne 'all') );
5207 # foreach my $problem ( @problems ) {
5208 # @records = @{$problem -> $accessor};
5209 # @records = ($records[$instance-1]) if ( $instance ne 'all' );
5210 # die "modelfile -> _get_option_val_pos: No record instance $instance ".
5211 # "of record $record_name in problem $problem_number exists\n"
5212 # if( (scalar @records < 1) and ($instance ne 'all') );
5213 # foreach my $record ( @records ) {
5215 # foreach my $option ( @{$record -> {'options'}} ) {
5216 # if ( defined $option and $option -> name eq $name) {
5217 # print "Found $name at $i\n" if ( $self -> {'debug'} );
5218 # push( @values, $option -> value );
5219 # push( @positions, $i );
5226 end _get_option_val_pos
5228 # }}} _get_option_val_pos
5234 # The I<add_if_absent> argument tells the method to add an init (theta,omega,sigma)
5235 # if the parameter number points to a non-existing parameter with parameter number
5236 # one higher than the highest presently included. Only applicatble if
5237 # I<new_values> are set. Default value = 0;
5239 unless( scalar @problem_numbers > 0 ){
5240 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5242 my @problems = @
{$self -> {'problems'}};
5243 if ( $#new_values >= 0 ) {
5244 'debug' -> die( message
=> "The number of new value sets " .
5245 $#new_values+1 . " do not" .
5246 " match the number of problems " . $#problem_numbers+1 . " specified" )
5247 unless(($#new_values == $#problem_numbers) );
5248 if ( $#parameter_numbers > 0 ) {
5249 'debug' -> die( message
=> "The number of parameter number sets do not" .
5250 " match the number of problems specified" )
5251 unless(($#parameter_numbers == $#problem_numbers) );
5255 my $new_val_idx = 0;
5256 foreach my $i ( @problem_numbers ) {
5257 if ( defined $problems[ $i-1 ] ) {
5258 if ( scalar @new_values > 0) {
5260 # Use attribute parameter_values to collect diagnostic outputs
5261 push( @parameter_values,
5262 $problems[ $i-1 ] ->
5263 _init_attr
( parameter_type
=> $parameter_type,
5264 parameter_numbers
=> $parameter_numbers[ $new_val_idx ],
5265 new_values
=> \@
{$new_values[ $new_val_idx ]},
5266 attribute
=> $attribute,
5267 add_if_absent
=> $add_if_absent ) );
5270 # {{{ Retrieve values
5271 push( @parameter_values,
5272 $problems[ $i-1 ] ->
5273 _init_attr
( parameter_type
=> $parameter_type,
5274 parameter_numbers
=> $parameter_numbers[ $i-1 ],
5275 attribute
=> $attribute ) );
5276 # }}} Retrieve values
5279 'debug' -> die( message
=> "Problem number $i does not exist!" );
5294 # $modobj -> _option_name ( record => $record_name,
5297 # This basic usage returns the name of the third option in the first
5298 # instance of the record specified by I<record>.
5301 my ( @problems, @records, @options, $i );
5302 my $accessor = $record.'s';
5303 if ( defined $self -> {'problems'} ) {
5304 @problems = @
{$self -> {'problems'}};
5306 'debug' -> die( message
=> "No problems defined in model" );
5308 if ( defined $problems[$problem_number - 1] -> $accessor ) {
5309 @records = @
{$problems[$problem_number - 1] -> $accessor};
5311 'debug' -> die( message
=> "No record $record defined in ".
5312 "problem number $problem_number." );
5314 if ( defined $records[$instance - 1] -> options
) {
5315 @options = @
{$records[$instance - 1] -> options
};
5317 'debug' -> die( message
=> "model -> _option_name: No option defined in record ".
5318 "$record in problem number $problem_number." );
5321 foreach my $option ( @options ) {
5322 if ( $i == $position ) {
5323 if ( defined $new_name ){
5324 $option -> name
($new_name) if ( defined $option );
5326 $name = $option -> name
if ( defined $option );
5336 # {{{ _parameter_count
5337 start _parameter_count
5339 if( defined $self -> {'problems'} ){
5340 my $problems = $self -> {'problems'};
5341 if( defined @
{$problems}[$problem_number - 1] ){
5342 $count = @
{$problems}[$problem_number - 1] -> record_count
( 'record_name' => $record );
5346 end _parameter_count
5347 # }}} _parameter_count
5349 # {{{ _read_problems
5351 start _read_problems
5354 # To read problems from a modelfile we need its full name
5355 # (meaning filename and path). And we need an array for the
5356 # modelfile lines and an array with indexes telling where
5357 # problems start in the modelfile array.
5360 my $file = $self -> full_name
;
5361 my ( @modelfile, @problems );
5362 my ( @problem_start_index );
5364 # Check if the file is missing, and if that is ok.
5365 # TODO Check accessor what happens if the file is missing.
5367 return if( not (-e
$file) && $self -> {'ignore_missing_files'} );
5369 # Open the file, slurp it and close it
5370 open( FILE
, "$file" ) ||
5371 'debug' -> die( message
=> "Model -> _read_problems: Could not open $file".
5373 @modelfile = <FILE
>;
5376 my @extra_data_files = defined $self ->{'extra_data_files'} ?
5377 @
{$self -> {'extra_data_files'}} : ();
5378 my @extra_data_headers = defined $self ->{'extra_data_headers'} ?
5379 @
{$self -> {'extra_data_headers'}} : ();
5382 # # Find the indexes where the problems start
5383 # for ( my $i = 0; $i <= $#modelfile; $i++ ) {
5384 # push( @problem_start_index, $i )if ( $modelfile[$i] =~ /\$PROB/ );
5387 # # Loop over the number of problems. Copy the each problems lines
5388 # # and create a problem object.
5390 # for( my $i = 0; $i <= $#problem_start_index; $i++ ) {
5391 # my $start_index = $problem_start_index[$i];
5392 # my $end_index = defined $problem_start_index[$i+1] ? $problem_start_index[$i+1] - 1: $#modelfile ;
5394 # my @problem_lines = @modelfile[$start_index .. $end_index];
5396 # # Problem object creation.
5397 # push( @problems, model::problem -> new ( debug => $self -> {'debug'},
5398 # ignore_missing_files => $self -> {'ignore_missing_files'},
5399 # prob_arr => \@problem_lines,
5400 # extra_data_file_name => $extra_data_files[$i],
5401 # extra_data_header => $extra_data_headers[$i]) );
5403 my $start_index = 0;
5408 # It may look like the loop takes one step to much, but its a
5409 # trick that helps parsing the last problem.
5410 for ( my $i = 0; $i <= @modelfile; $i++ ) {
5411 if( $i <= $#modelfile ){
5412 $_ = $modelfile[$i];
5415 # In this if statement we use the lazy evaluation of logical
5416 # or to make sure we only execute search pattern when we have
5417 # a line to search. Which is all cases but the very last loop
5420 if( $i > $#modelfile or /\$PROB/ ){
5423 # The if statement here is only necessary in the first loop
5424 # iteration. When start_index == end_index == 0 we want to
5425 # skip to the next iteration looking for the actual end of
5426 # the first problem.
5428 if( $end_index > $start_index and not $first ){
5429 # extract lines of code:
5430 my @problem_lines = @modelfile[$start_index .. $end_index-1];
5431 # reset the search for problems by moving the problem start
5435 my $sh_mod = model
::shrinkage_module
-> new
( model
=> $self,
5436 temp_problem_number
=> ($#problems+2));
5437 push( @problems, model
::problem
->
5438 new
( directory
=> $self -> {'directory'},
5439 ignore_missing_files
=> $self -> {'ignore_missing_files'},
5440 ignore_missing_output_files
=> $self -> {'ignore_missing_output_files'},
5441 sde
=> $self -> {'sde'},
5442 prob_arr
=> \
@problem_lines,
5443 extra_data_file_name
=> $extra_data_files[$prob_num],
5444 extra_data_header
=> $extra_data_headers[$prob_num],
5445 shrinkage_module
=> $sh_mod ) );
5447 $sh_mod -> problem
( $problems[$#problems] );
5454 # Set the problems in the modelobject.
5455 $self -> problems
(\
@problems);
5459 # }}} _read_problems
5465 unless( $#problem_numbers >= 0 ){
5466 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5469 my @problems = @
{$self -> {'problems'}};
5470 foreach my $i ( @problem_numbers ) {
5471 if ( defined $problems[ $i-1 ] ) {
5472 my $found = $self -> is_option_set
( 'problem_number' => $i,
5473 'record' => $record_name,
5474 'name' => $option_name );
5475 $problems[$i-1] -> remove_option
( record_name
=> $record_name,
5476 option_name
=> $option_name ) if ( $found );
5477 $problems[$i-1] -> add_option
( record_name
=> $record_name,
5478 option_name
=> $option_name,
5479 option_value
=> $option_value );
5491 unless( $#problem_numbers >= 0 ){
5492 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5495 my @problems = @
{$self -> {'problems'}};
5496 foreach my $i ( @problem_numbers ) {
5497 if ( defined $problems[ $i-1 ] ) {
5498 $problems[$i-1] -> add_option
( record_name
=> $record_name,
5499 option_name
=> $option_name,
5500 option_value
=> $option_value,
5501 add_record
=> $add_record );
5513 unless( $#problem_numbers >= 0 ){
5514 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5517 my @problems = @
{$self -> {'problems'}};
5518 foreach my $i ( @problem_numbers ) {
5519 if ( defined $problems[ $i-1 ] ) {
5520 $problems[$i-1] -> remove_option
( record_name
=> $record_name,
5521 option_name
=> $option_name );
5529 # {{{ _option_val_pos
5531 start _option_val_pos
5533 unless( $#problem_numbers >= 0 ){
5534 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5536 my @problems = @
{$self -> {'problems'}};
5537 if ( $#new_values >= 0 ) {
5538 'debug' -> die( message
=> "Trying to set option $name in record $record_name but the ".
5539 "number of new value sets (".
5541 "), do not match the number of problems specified (".
5542 ($#problem_numbers+1).")" )
5543 unless(($#new_values == $#problem_numbers) );
5544 if ( $#instance_numbers > 0 ) {
5545 'debug' -> die( message
=> "The number of instance number sets (".
5546 ($#instance_numbers+1).
5547 "),do not match the number of problems specified (".
5548 ($#problem_numbers+1).")" )
5549 unless(($#instance_numbers == $#problem_numbers) );
5553 foreach my $i ( @problem_numbers ) {
5554 if ( defined $problems[ $i-1 ] ) {
5555 my $rn_ref = $#instance_numbers >= 0 ? \@
{$instance_numbers[ $i-1 ]} : [];
5556 if ( scalar @new_values > 0) {
5559 if( not defined $new_values[ $i-1 ] ) {
5560 debug
-> die( message
=> " The specified new_values was undefined for problem $i" );
5563 if( not ref( $new_values[ $i-1 ] ) eq 'ARRAY' ) {
5564 debug
-> die( message
=> " The specified new_values for problem $i is not an array as it should be but a ".
5565 ( defined ref( $new_values[ $i-1 ] ) ?
5566 ref( $new_values[ $i-1 ] ) : 'undef' ) );
5569 $problems[ $i-1 ] ->
5570 _option_val_pos
( record_name
=> $record_name,
5571 instance_numbers
=> $rn_ref,
5572 new_values
=> \@
{$new_values[ $i-1 ]},
5574 exact_match
=> $exact_match );
5578 # {{{ Retrieve values
5579 my ( $val_ref, $pos_ref ) =
5580 $problems[ $i-1 ] ->
5581 _option_val_pos
( record_name
=> $record_name,
5582 instance_numbers
=> $rn_ref,
5584 exact_match
=> $exact_match );
5585 push( @values, $val_ref );
5586 push( @positions, $pos_ref );
5587 # }}} Retrieve values
5590 'debug' -> die( message
=> "Problem number $i does not exist!" );
5596 # }}} _option_val_pos
5598 # {{{ subroutine_files
5600 start subroutine_files
5603 foreach my $subr( 'PRED','CRIT', 'CONTR', 'CCONTR', 'MIX', 'CONPAR', 'OTHER', 'PRIOR' ){
5604 my ( $model_fsubs, $junk ) = $self -> _option_val_pos
( record_name
=> 'subroutine',
5606 if( @
{$model_fsubs} > 0 ){
5607 foreach my $prob_fsubs ( @
{$model_fsubs} ){
5608 foreach my $fsub( @
{$prob_fsubs} ){
5615 @fsubs = keys %fsubs;
5617 for( my $i = 0; $i <= $#fsubs; $i ++ ){
5618 unless( $fsubs[$i] =~ /\.f$/ ){
5624 end subroutine_files