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 # TODO Remove this if it works
159 #my $subroutine_files = $this -> subroutine_files;
160 #if( defined $subroutine_files and scalar @{$subroutine_files} > 0 ){
161 # push( @{$this -> {'extra_files'}}, @{$subroutine_files} );
164 if ( defined $this -> {'extra_files'} ){
165 for( my $i; $i < scalar @
{$this -> {'extra_files'}}; $i++ ){
166 my ( $dir, $file ) = OSspecific
::absolute_path
( $this -> {'directory'}, $this -> {'extra_files'} -> [$i]);
167 $this -> {'extra_files'} -> [$i] = $dir . $file;
171 # Read datafiles, if any.
172 unless( defined $this -> {'datas'} and not $this -> {'quick_reload'} ){
173 my @idcolumns = @
{$this -> idcolumns
};
174 my @datafiles = @
{$this -> datafiles
('absolute_path' => 1)};
175 # my @datafiles = @{$this -> datafiles('absolute_path' => 0)};
176 for ( my $i = 0; $i <= $#datafiles; $i++ ) {
177 my $datafile = $datafiles[$i];
178 my $idcolumn = $idcolumns[$i];
179 my ( $cont_column, $wrap_column ) = $this -> {'problems'} -> [$i] -> cont_wrap_columns
;
180 my $ignoresign = defined $this -> ignoresigns ?
$this -> ignoresigns
-> [$i] : undef;
181 my @model_header = @
{$this -> {'problems'} -> [$i] -> header
};
182 if ( defined $idcolumn ) {
183 push ( @
{$this -> {'datas'}}, data
->
184 new
( idcolumn
=> $idcolumn,
185 filename
=> $datafile,
186 cont_column
=> $cont_column,
187 wrap_column
=> $wrap_column,
188 #model_header => \@model_header,
189 ignoresign
=> $ignoresign,
190 directory
=> $this -> {'directory'},
191 ignore_missing_files
=> $this -> {'ignore_missing_files'} ||
192 $this -> {'ignore_missing_data'},
193 target
=> $this -> {'target'}) );
195 'debug' -> die( message
=> "New model to be created from ".$this -> full_name
().
196 ". Data file is ".$datafile.
197 ". No id column definition found in the model file." );
202 # Read outputfile, if any.
203 if( ! defined $this -> {'outputs'} ) {
204 unless( defined $this -> {'outputfile'} ){
205 if( $this -> filename
() =~ /\.mod$/ ) {
206 ($this -> {'outputfile'} = $this -> {'filename'}) =~ s/\.mod$/.lst/;
208 $this -> outputfile
( $this -> filename
().'.lst' );
211 push ( @
{$this -> {'outputs'}}, output
->
212 new
( filename
=> $this -> {'outputfile'},
213 directory
=> $this -> {'directory'},
214 ignore_missing_files
=>
215 $this -> {'ignore_missing_files'} || $this -> {'ignore_missing_output_files'},
216 target
=> $this -> {'target'},
217 model_id
=> $this -> {'model_id'} ) );
220 # Adding mirror_plots module here, since it can add
221 # $PROBLEMS. Also it needs to know wheter an lst file exists
224 if( $this -> {'mirror_plots'} > 0 ){
225 my $mirror_plot_module = model
::mirror_plot_module
-> new
( base_model
=> $this,
226 nr_of_mirrors
=> $this -> {'mirror_plots'},
227 cwres
=> $this -> {'cwres'},
228 mirror_from_lst
=> $this -> {'mirror_from_lst'});
229 push( @
{$this -> {'mirror_plot_modules'}}, $mirror_plot_module );
232 if( $this -> {'iofv'} > 0 ){
233 my $iofv_module = model
::iofv_module
-> new
( base_model
=> $this,
234 nm_version
=> $this -> {'nm_version'});
235 push( @
{$this -> {'iofv_modules'}}, $iofv_module );
243 # {{{ register_in_database
245 start register_in_database
247 if ( $PsN::config
-> {'_'} -> {'use_database'} ) {
248 # Backslashes messes up the sql syntax
249 my $file_str = $self->{'filename'};
250 my $dir_str = $self->{'directory'};
251 $file_str =~ s/\\/\//g
;
252 $dir_str =~ s/\\/\//g
;
255 my $md5sum = md5_hex
(OSspecific
::slurp_file
($self-> full_name
));
257 my $dbh = DBI
-> connect("DBI:mysql:host=".$PsN::config
-> {'_'} -> {'database_server'}.
258 ";databse=".$PsN::config
-> {'_'} -> {'project'},
259 $PsN::config
-> {'_'} -> {'user'},
260 $PsN::config
-> {'_'} -> {'password'},
261 {'RaiseError' => 1});
268 my $sth = $dbh -> prepare
( "SELECT model_id FROM ".$PsN::config
-> {'_'} -> {'project'}.
270 "WHERE filename = '$file_str' AND ".
271 "directory = '$dir_str' AND ".
272 "md5sum = '".$md5sum."'" );
273 $sth -> execute
or 'debug' -> die( message
=> $sth->errstr ) ;
275 $select_arr = $sth -> fetchall_arrayref
;
278 if ( scalar @
{$select_arr} > 0 ) {
279 'debug' -> warn( level
=> 1,
280 message
=> "Found an old entry in the database matching the ".
281 "current model file" );
282 if ( scalar @
{$select_arr} > 1 ) {
283 'debug' -> warn( level
=> 1,
284 message
=> "Found more than one matching entry in database".
285 ", using the first" );
287 $self -> {'model_id'} = $select_arr->[0][0];
289 my ( $date_str, $time_str );
290 if( $Config{osname
} eq 'MSWin32' ){
291 $date_str = `date /T`;
292 $time_str = ' '.`time /T`;
299 my $date_time = $date_str.$time_str;
300 $sth = $dbh -> prepare
("INSERT INTO ".$PsN::config
-> {'_'} -> {'project'}.
301 ".model (filename,date,directory,md5sum) ".
302 "VALUES ('$file_str', '$date_time', '$dir_str','".
305 $self -> {'model_id'} = $sth->{'mysql_insertid'};
307 $sth -> finish
if ( defined $sth );
310 $model_id = $self -> {'model_id'} # return the model_id;
312 end register_in_database
314 # }}} register_in_database
316 # {{{ shrinkage_stats
318 start shrinkage_stats
320 if ( $#problem_numbers > 0 and ref $enabled eq 'ARRAY' ){
321 if ( $#problem_numbers != ( scalar @
{$enabled} - 1 ) ) {
322 'debug' -> die( message
=> "The number of problem_numbers ".($#problem_numbers+1).
323 "and enabled/disabled shrinkage_stats ".scalar @
{$enabled}.
327 unless( $#problem_numbers > 0 ){
328 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
331 if( ref \
$enabled eq 'SCALAR' ) {
332 for ( @problem_numbers ) {
333 push( @en_arr, $enabled );
335 } elsif ( not ref $enabled eq 'ARRAY' ) {
336 debug
-> die( message
=> 'enabled must be a scalar or a reference to an array, '.
337 'not a reference to a '.ref($enabled).'.' );
340 my @problems = @
{$self -> {'problems'}};
342 foreach my $i ( @problem_numbers ) {
343 if ( defined $problems[ $i-1 ] ) {
344 if ( defined $en_arr[ $j ] ) {
345 if( $en_arr[ $j ] ) {
346 $problems[ $i-1 ] -> shrinkage_module
-> enable
;
348 $problems[ $i-1 ] -> shrinkage_module
-> disable
;
350 # my $eta_file = $self -> filename.'_'.$i.'.etas';
351 # my $eps_file = $self -> filename.'_'.$i.'.wres';
352 # $problems[ $i-1 ] -> {'eta_shrinkage_table'} = $eta_file;
353 # $problems[ $i-1 ] -> {'wres_shrinkage_table'} = $eps_file;
355 push( @indicators, $problems[ $i-1 ] -> shrinkage_module
-> status
);
358 'debug' -> die( message
=> "Problem number $i does not exist!" );
365 # }}} shrinkage_stats
369 =head2 wres_shrinkage
375 my $wres_shrink = $model_object -> wres_shrinkage();
381 Calculates wres shrinkage, a table file with wres is necessary. The
382 return value is reference of and array with one an array per problem
389 my @problems = @
{$self -> {'problems'}};
390 foreach my $problem ( @problems ) {
391 push( @wres_shrinkage, $problem -> wres_shrinkage
);
406 my $eta_shrink = $model_object -> eta_shrinkage();
412 Calculates eta shrinkage, a table file with eta is necessary. The
413 return value is reference of and array with one an array per problem
420 my @problems = @
{$self -> {'problems'}};
421 foreach my $problem ( @problems ) {
422 push( @eta_shrinkage, $problem -> eta_shrinkage
);
429 # {{{ nonparametric_code
431 start nonparametric_code
433 if ( $#problem_numbers > 0 and $#enabled > 0 ){
434 if ( $#problem_numbers != $#enabled ) {
435 'debug' -> die( message
=> "The number of problem_numbers ".($#problem_numbers+1).
436 "and enabled/disabled nonparametric_code ".($#enabled+1).
440 unless( $#problem_numbers > 0 ){
441 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
443 my @problems = @
{$self -> {'problems'}};
445 foreach my $i ( @problem_numbers ) {
446 if ( defined $problems[ $i-1 ] ) {
447 if ( defined $enabled[ $j ] ) {
448 $problems[ $i-1 ] -> nonparametric_code
( $enabled[ $j ] );
450 push( @indicators, $problems[ $i-1 ] -> nonparametric_code
);
453 'debug' -> die( message
=> "Problem number $i does not exist!" );
458 end nonparametric_code
460 # }}} nonparametric_code
462 # {{{ add_nonparametric_code
464 start add_nonparametric_code
466 $self -> set_records
( type
=> 'nonparametric',
467 record_strings
=> [ 'MARGINALS UNCONDITIONAL' ] );
468 $self -> set_option
( record_name
=> 'estimation',
469 option_name
=> 'POSTHOC' );
470 my ( $msfo_ref, $junk ) = $self ->
471 _get_option_val_pos
( name
=> 'MSFO',
472 record_name
=> 'estimation' );
473 my @nomegas = @
{$self -> nomegas
};
475 for( my $i = 0; $i <= $#nomegas; $i++ ) { # loop the problems
477 for( my $j = 0; $j <= $nomegas[$i]; $j++ ) {
478 $marg_str = $marg_str.' COM('.($j+1).')=MG'.($j+1);
480 $marg_str = $marg_str.' FILE='.$self->filename.'.marginals'.
481 ' NOAPPEND ONEHEADER NOPRINT';
482 $self -> add_records
( problem_numbers
=> [($i+1)],
484 record_strings
=> [ $marg_str ] );
485 $self -> remove_option
( record_name
=> 'abbreviated',
486 option_name
=> 'COMRES' );
487 $self -> add_option
( record_name
=> 'abbreviated',
488 option_name
=> 'COMRES',
489 option_value
=> ($nomegas[$i]+1),
490 add_record
=> 1 ); #Add $ABB if not existing
492 $self -> add_marginals_code
( problem_numbers
=> [($i+1)],
493 nomegas
=> [ $nomegas[$i] ] );
496 if( not defined $msfo_ref ) {
497 for( my $i = 0; $i < $self -> nproblems
; $i++ ) {
498 $self -> add_option
( record_name
=> 'estimation',
499 option_name
=> 'MSFO',
500 option_value
=> $self -> filename
.'.msfo'.($i+1) );
503 for( my $i = 0; $i < scalar @
{$msfo_ref}; $i++ ) {
504 if( not defined $msfo_ref->[$i] or not defined $msfo_ref->[$i][0] ) {
505 $self -> add_option
( record_name
=> 'estimation',
506 option_name
=> 'MSFO',
507 option_value
=> $self -> filename
.'.msfo'.($i+1) );
512 end add_nonparametric_code
514 # }}} add_nonparametric_code
524 $model_object -> flush_data();
530 flush data calls the same method on each data object (usually one)
531 which causes it to write data to disk and remove its data from memory.
537 if ( defined $self -> {'datas'} ) {
538 foreach my $data ( @
{$self -> {'datas'}} ) {
553 C<< my $file_name = $model_object -> full_name(); >>
557 full_name will return the name of the modelfile and its directory in a
558 string. For example: "/users/guest/project/model.mod".
564 $full_name = $self -> {'directory'} . $self -> {'filename'};
572 This function is unused
and should probably be removed
.
574 # start __sync_output
576 unless( defined $self -> {'outputfile'} ){
577 'debug' -> die( message
=> "No output file is set, cannot synchronize output" );
579 @
{$self -> {'outputs'}} = ();
580 push ( @
{$self -> {'outputs'}}, output
->
581 new
( filename
=> $self -> {'outputfile'},
582 ignore_missing_files
=> $self -> {'ignore_missing_files'},
583 target
=> $self -> {'target'},
584 model_id
=> $self -> {'model_id'} ) );
590 # {{{ add_marginals_code
592 start add_marginals_code
594 # add_marginals_code takes two arguments.
596 # - problem_numbers is an array holding the numbers of the problems in
597 # which code should be added.
599 # - nomegas which is an array holding the number of (diagonal-element)
600 # omegas of each problem given by problem_numbers.
602 # For each omega in each problem, verbatim code is added to make the
603 # marginals available for printing (e.g. to a table file). COM(1) will
604 # hold the nonparametric density, COM(2) the marginal cumulative value
605 # for the first eta, COM(2) the marginal cumulative density for the
606 # second eta and so on.
608 unless( $#problem_numbers >= 0 ){
609 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
612 my @problems = @
{$self -> {'problems'}};
614 foreach my $i ( @problem_numbers ) {
615 if ( defined $problems[ $i-1 ] ) {
616 $problems[$i-1] -> add_marginals_code
( nomegas
=> $nomegas[ $j ] );
618 'debug' -> die( message
=> "Problem number $i does not exist.");
623 end add_marginals_code
625 # }}} add_marginals_code
635 $model_object -> add_records( type => 'THETA',
636 record_strings => ['(0.1,15,23)'] );
652 =item problem_numbers
660 add_records is used to add NONMEM control file records to the model
661 object. The "type" argument is mandatory and must be a valid NONMEM
662 record name, such as "PRED" or "THETA". Otherwise an error will be
663 output and the program terminated (this is object to change, ideally
664 we would only report an error and let the caller deal with it). The
665 "record_strings" argument is a mandatory array of valid NONMEM record
666 code. Each array corresponds to a line of the record code. There
667 "problem_numbers" argument is optional and is an array of problems
668 numbered from 1 for which the record is added, by default the record
669 is added to all problems.
671 Notice that the records are appended to those that allready exists,
672 which makes sence for records that do not exist and for initial
673 values. For records like "DATA" or "PRED" you probably want to use
680 unless( $#problem_numbers >= 0 ){
681 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
684 my @problems = @
{$self -> {'problems'}};
685 foreach my $i ( @problem_numbers ) {
686 if ( defined $problems[ $i-1 ] ) {
687 # if( defined $self -> {'problems'} ){
688 # if( defined @{$self -> {'problems'}}[$problem_number - 1] ){
689 # my $problem = @{$self -> {'problems'}}[$problem_number - 1];
690 # $problem -> add_records( 'type' => $type,
691 # 'record_strings' => \@record_strings );
692 $problems[$i-1] -> add_records
( 'type' => $type,
693 'record_strings' => \
@record_strings );
695 'debug' -> die( message
=> "Problem number $i does not exist.");
699 # 'debug' -> die( message => "Model -> add_records: No Problems in model object.") ;
714 $model_object -> set_records( type => 'THETA',
715 record_strings => ['(0.1,15,23)'] );
731 =item problem_numbers
739 set_records works just like add_records but will replace any existing
740 records in the model object.
746 unless( $#problem_numbers >= 0 ){
747 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
750 my @problems = @
{$self -> {'problems'}};
751 foreach my $i ( @problem_numbers ) {
752 if ( defined $problems[ $i-1 ] ) {
753 # if( defined $self -> {'problems'} ){
754 # if( defined @{$self -> {'problems'}}[$problem_number - 1] ){
755 # my $problem = @{$self -> {'problems'}}[$problem_number - 1];
756 # $problem -> set_records( 'type' => $type,
757 # 'record_strings' => \@record_strings );
758 $problems[$i-1] -> set_records
( 'type' => $type,
759 'record_strings' => \
@record_strings );
761 'debug' -> die( message
=> "Problem number $i does not exist." );
765 # 'debug' -> die( "No Problems in model object.") ;
774 =head2 remove_records
780 $model_object -> remove_records( type => 'THETA' )
792 =item problem_numbers
800 remove_records removes the record given in the "type" argument which
801 must be a valid NONMEM record name.
807 unless( $#problem_numbers >= 0 ){
808 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
811 my @problems = @
{$self -> {'problems'}};
812 foreach my $i ( @problem_numbers ) {
813 if ( defined $problems[ $i-1 ] ) {
814 # if( defined $self -> {'problems'} ){
815 # if( defined @{$self -> {'problems'}}[$problem_number - 1] ){
816 # my $problem = @{$self -> {'problems'}}[$problem_number - 1];
817 # $problem -> remove_records( 'type' => $type );
818 $problems[$i-1] -> remove_records
( 'type' => $type );
820 'debug' -> die( message
=> "Problem number $i, does not exist" );
824 # 'debug' -> die( message => "No Problems in model object." );
839 $model_object -> copy( filename => 'copy.mod',
865 =item data_file_names
871 string with value 'disk' or 'mem'
873 =item extra_data_file_names
877 =item update_shrinkage_tables
885 copy produces a new modelfile object and a new file on disk whose name
886 is given by the "filename" argument. To create copies of data file the
887 copy_data options may be set to 1. The values of "data_file_names",
888 unless given, will be the model file name but with '.mod' exchanged
889 for '_$i.dta', where $i is the problem number. If data is not copied,
890 a new data object will be intialized from the same data file as the
891 previous model and "data_file_names" WILL BE IGNORED. This has the
892 side effect that the data file can be modified from both the original
893 model and the copy. The same holds for "extra_data_files". It is
894 possible to set "copy_output" to 1 as well, which then copies the
895 output object instead of reading the output file from disk, which is
896 slower. Since output objects are meant to be read-only, no
897 output_filename can be specified and the output object copy will
898 reside in memory only.
900 The "target" option has no effect.
906 # PP_TODO fix a nice copying of modelfile data
907 # preferably in memory copy. Perhaps flush data ?
909 # Check sanity of the length of data file names argument
910 if ( scalar @data_file_names > 0 ) {
911 'debug' -> die( message
=> "model -> copy: The number of specified new data file " .
912 "names ". scalar @data_file_names. "must\n match the number".
913 " of data objects connected to the model object".
914 scalar @
{$self -> {'datas'}} )
915 unless ( scalar @data_file_names == scalar @
{$self -> {'datas'}} );
918 ($d_filename = $filename) =~ s/\.mod$//;
919 for ( my $i = 1; $i <= scalar @
{$self -> {'datas'}}; $i++ ) {
920 # Data filename is created in this directory (no directory needed).
921 push( @data_file_names, $d_filename."_data_".$i."_copy.dta" );
925 # Check sanity of the length of extra_data file names argument
926 if ( scalar @extra_data_file_names > 0 ) {
927 'debug' -> die( message
=> "The number of specified new extra_data file ".
928 "names ". scalar @extra_data_file_names, "must\n match the number".
929 " of problems (one extra_data file per prolem)".
930 scalar @
{$self -> {'extra_data_files'}} )
931 unless( scalar @extra_data_file_names == scalar @
{$self -> {'extra_data_files'}} );
933 if ( defined $self -> {'extra_data_files'} ) {
935 ($d_filename = $filename) =~ s/\.mod$//;
936 for ( my $i = 1; $i <= scalar @
{$self -> {'extra_data_files'}}; $i++ ) {
937 # Extra_Data filename is created in this directory (no directory needed).
938 push( @extra_data_file_names, $d_filename."_extra_data_".$i."_copy.dta" );
943 ($directory, $filename) = OSspecific
::absolute_path
( $directory, $filename );
947 # save references to own data and output objects
948 my $datas = $self -> {'datas'};
949 # $Data::Dumper::Maxdepth = 2;
950 # die "MC1: ", Dumper $datas -> [0] -> {'individuals'};
951 my $outputs = $self -> {'outputs'};
953 my @problems = @
{$self -> {'problems'}};
954 for ( my $i = 0; $i <= $#problems; $i++ ) {
955 if ( defined $problems[$i] -> {'extra_data'} ) {
956 $extra_datas{$i} = $problems[$i] -> {'extra_data'};
960 my ( @new_datas, @new_extra_datas, @new_outputs );
962 $self -> synchronize
if not $self -> {'synced'};
964 # remove ref to data and output object to speed up the
966 $self -> {'datas'} = undef;
967 $self -> {'outputs'} = undef;
968 for ( my $i = 0; $i <= $#problems; $i++ ) {
969 $problems[$i] -> {'extra_data'} = undef;
972 # Copy the data objects if so is requested
973 if ( defined $datas ) {
975 foreach my $data ( @
{$datas} ) {
976 if ( $copy_data == 1 ) {
977 push( @new_datas, $data ->
978 copy
( filename
=> $data_file_names[$i]) );
980 # This line assumes one data per problem! May be a source of error.
981 my ( $cont_column, $wrap_column ) = $self -> problems
-> [$i] -> cont_wrap_columns
;
982 my $ignoresign = defined $self -> ignoresigns ?
$self -> ignoresigns
-> [$i] : undef;
983 my @model_header = @
{$self -> problems
-> [$i] -> header
};
984 push @new_datas, data
->
985 new
( filename
=> $data -> filename
,
986 directory
=> $data -> directory
,
987 cont_column
=> $cont_column,
988 wrap_column
=> $wrap_column,
989 #model_header => \@model_header,
991 ignoresign
=> $ignoresign,
992 idcolumn
=> $data -> idcolumn
);
998 # Copy the extra_data objects if so is requested
999 for ( my $i = 0; $i <= $#problems; $i++ ) {
1000 my $extra_data = $extra_datas{$i};
1001 if ( defined $extra_data ) {
1002 if ( $copy_data == 1 ) {
1003 push( @new_extra_datas, $extra_data ->
1004 copy
( filename
=> $extra_data_file_names[$i]) );
1006 push( @new_extra_datas, extra_data
->
1007 new
( filename
=> $extra_data -> filename
,
1008 directory
=> $extra_data -> directory
,
1010 idcolumn
=> $extra_data -> idcolumn
) );
1016 # Clone self into new model object and set synced to 0 for
1018 $new_model = Storable
::dclone
( $self );
1019 $new_model -> {'synced'} = 0;
1021 # $Data::Dumper::Maxdepth = 3;
1022 # die Dumper $new_datas[0] -> {'individuals'};
1024 # Restore the data and output objects for self
1025 $self -> {'datas'} = $datas;
1026 $self -> {'outputs'} = $outputs;
1027 for ( my $i = 0; $i <= $#problems; $i++ ) {
1028 if( defined $extra_datas{$i} ){
1029 $problems[$i] -> {'extra_data'} = $extra_datas{$i};
1033 # Set the new file name for the copy
1034 $new_model -> directory
( $directory );
1035 $new_model -> filename
( $filename );
1037 # {{{ update the shrinkage modules
1039 my @problems = @
{$new_model -> problems
};
1040 for( my $i = 1; $i <= scalar @problems; $i++ ) {
1041 $problems[ $i-1 ] -> shrinkage_module
-> model
( $new_model );
1044 # }}} update the shrinkage modules
1046 # Copy the output object if so is requested (only one output
1047 # object defined per model object)
1048 if ( defined $outputs ) {
1049 foreach my $output ( @
{$outputs} ) {
1050 if ( $copy_output == 1 ) {
1051 push( @new_outputs, $output -> copy
);
1053 my $new_out = $filename;
1054 if( $new_out =~ /\.mod$/ ) {
1055 $new_out =~ s/\.mod$/\.lst/;
1057 $new_out = $new_out.'.lst';
1059 push( @new_outputs, output
->
1060 new
( filename
=> $new_out,
1061 directory
=> $directory,
1063 ignore_missing_files
=> 1,
1064 model_id
=> $new_model -> {'model_id'} ) );
1069 # Add the copied data and output objects to the model copy
1070 $new_model -> datas
( \
@new_datas );
1072 if ( $#new_extra_datas >= 0 ) {
1073 my @new_problems = @
{$new_model -> problems
};
1074 for ( my $i = 0; $i <= $#new_problems; $i++ ) {
1075 $new_problems[$i] -> {'extra_data'} = $new_extra_datas[$i];
1076 if ( $copy_data == 1 ){
1077 $new_problems[$i] -> {'extra_data_file_name'} = $extra_data_file_names[$i];
1082 $new_model -> {'outputs'} = \
@new_outputs;
1084 $new_model -> _write
;
1086 $new_model -> synchronize
if $target eq 'disk';
1100 my $indicators = $model_object -> covariance( enabled => [1] );
1112 =item problem_numbers
1120 covariance will let you turn the covariance step on and off per
1121 problem. The "enabled" argument is an array which must have a length
1122 equal to the number of problems. Each element set to 0 will disable
1123 the covariance step for the corresponding problem. And conversely each
1124 element set to nonzero will enable the covariance step.
1126 covariance will return an array with an element for each problem, the
1127 element will indicate whether the covariance step is turned on or not.
1133 if ( $#problem_numbers > 0 ){
1134 if ( $#problem_numbers != $#enabled ) {
1135 'debug' -> die( message
=> "The number of problem_numbers ".($#problem_numbers+1).
1136 "and enabled/disabled covariance records ".($#enabled+1).
1140 unless( $#problem_numbers > 0 ){
1141 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
1143 my @problems = @
{$self -> {'problems'}};
1145 foreach my $i ( @problem_numbers ) {
1146 if ( defined $problems[ $i-1 ] ) {
1147 if ( defined $enabled[ $j ] ) {
1148 $problems[ $i-1 ] -> covariance
( enabled
=> $enabled[ $j ] );
1150 push( @indicators, $problems[ $i-1 ] -> covariance
);
1153 'debug' -> die( message
=> "Problem number $i does not exist!" );
1170 $model_object -> datas( [$data_obj] );
1172 my $data_objects = $model_object -> data;
1178 The argument is an unnamed array of data objects.
1182 If data is used without argument the data objects connected to the
1183 model object is returned. If an argument is given it must be an array
1184 of length equal to the number of problems with data objects. Those
1185 objects will replace any existing data objects and their filenames
1186 will be put in the model files records.
1192 my $nprobs = scalar @
{$self -> {'problems'}};
1193 if ( defined $parm ) {
1194 if ( ref($parm) eq 'ARRAY' ) {
1195 my @new_datas = @
{$parm};
1196 # Check that new_headers and problems match
1197 'debug' -> die( message
=> "The number of problems $nprobs and".
1198 " new data ". ($#new_datas+1) ." don't match in ".
1199 $self -> full_name
) unless ( $#new_datas + 1 == $nprobs );
1200 if ( defined $self -> {'problems'} ) {
1201 for( my $i = 0; $i < $nprobs; $i++ ) {
1202 $self -> _option_name
( position
=> 0,
1204 problem_number
=> $i+1,
1205 new_name
=> $new_datas[$i] -> filename
);
1208 'debug' -> die( message
=> "No problems defined in ".
1209 $self -> full_name
);
1212 'debug' -> die( message
=> "Supplied new value is not an array" );
1223 # I have removed this because it was only used in the bootstrap. I
1224 # fixed the bootstrap to use datafiles instead. Also the bootstrap
1225 # methods who used this was very old and should probably be removed as
1230 # datafile either retrieves or sets a new name for the datafile in the first problem of the
1231 # model. This method is only here for compatibility reasons. Don't use it. Use L</datafiles> instead.
1233 if( defined $new_name ){
1234 $self -> _option_name
( position
=> 0,
1236 problem_number
=> $problem_number,
1237 new_name
=> $new_name);
1238 my ( $cont_column, $wrap_column ) = $self -> problems
-> [$problem_number-1] ->
1240 my $ignoresign = defined $self -> ignoresigns ?
1241 $self -> ignoresigns
-> [$problem_number-1] : undef;
1242 my @model_header = @
{$self -> problems
-> [$problem_number-1] -> header
};
1243 $self -> {'datas'} -> [$problem_number-1] = data
->
1244 new
( idcolumn
=> $self -> idcolumn
( problem_number
=> $problem_number ),
1245 ignoresign
=> $ignoresign,
1246 filename
=> $new_name,
1247 cont_column
=> $cont_column,
1248 wrap_column
=> $wrap_column,
1249 #model_header => \@model_header,
1250 ignore_missing_files
=> $self -> {'ignore_missing_files'},
1251 target
=> $self -> {'target'} );
1253 $name = $self -> _option_name
( position
=> 0, record
=> 'data', problem_number
=> $problem_number );
1268 $model_object -> datafiles( new_names => ['datafile.dta'] );
1280 =item problem_numbers
1292 datafiles changes the names of the data files in a model file. The
1293 "new_names" argument is an array of strings, where each string gives
1294 the file name of a problem data file. The length of "new_names" must
1295 be equal to the "problem_numbers" argument. "problem_numbers" is by
1296 default containing all of the models problems numbers. In the example
1297 above we only have one problem in the model file and therefore only
1298 need to give on new file name.
1300 Unless new_names is given datafiles returns the names of the data
1301 files used by the model file. If the optional "absolute_path" argument
1302 is given, the returned file names will have the path to file as well.
1308 # The datafiles method retrieves or sets the names of the
1309 # datafiles specified in the $DATA record of each problem. The
1310 # problem_numbers argument can be used to control which
1311 # problem that is affected. If absolute_path is set to 1, the
1312 # returned file names are given with absolute paths.
1314 unless( $#problem_numbers > 0 ){
1315 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
1317 if ( scalar @new_names > 0 ) {
1319 my @idcolumns = @
{$self ->
1320 idcolumns
( problem_numbers
=> \
@problem_numbers )};
1321 foreach my $new_name ( @new_names ) {
1322 if ( $absolute_path ) {
1324 ($tmp, $new_name) = OSspecific
::absolute_path
('', $new_name );
1325 $new_name = $tmp . $new_name;
1328 $self -> _option_name
( position
=> 0,
1330 problem_number
=> $problem_numbers[$i],
1331 new_name
=> $new_name);
1332 my ( $cont_column, $wrap_column ) = $self -> problems
->
1333 [$problem_numbers[$i]-1] -> cont_wrap_columns
;
1334 my $ignoresign = defined $self -> ignoresigns ?
$self -> ignoresigns
-> [$i] : undef;
1335 my @model_header = @
{$self -> problems
-> [$i] -> header
};
1336 $self -> {'datas'} -> [$problem_numbers[$i]-1] = data
->
1337 new
( idcolumn
=> $idcolumns[$i],
1338 ignoresign
=> $ignoresign,
1339 filename
=> $new_name,
1340 cont_column
=> $cont_column,
1341 wrap_column
=> $wrap_column,
1342 #model_header => \@model_header,
1343 ignore_missing_files
=> $self -> {'ignore_missing_files'},
1344 target
=> $self -> {'target'} );
1348 foreach my $prob_num ( @problem_numbers ) {
1349 if ( $absolute_path ) {
1350 my ($d_dir, $d_name);
1352 OSspecific
::absolute_path
($self -> {'directory'}, $self ->_option_name( position
=> 0,
1354 problem_number
=> $prob_num ) );
1355 push( @names, $d_dir . $d_name );
1357 my $name = $self -> _option_name
( position
=> 0,
1359 problem_number
=> $prob_num );
1360 $name =~ s/.*[\/\\]//;
1361 push( @names, $name );
1373 # This method is renamed __des in dia but not here. If nothing broke
1374 # until now I think we can safely remove it.
1378 # Returns the des part specified subproblem.
1379 # TODO: Even though new_des can be specified, they wont be set
1382 my @prob = @
{$self -> problems
};
1383 my @des = @
{$prob[$problem_number - 1] -> get_record
('des') -> code
}
1384 if ( defined $prob[$problem_number - 1] -> get_record
('des') );
1393 $self -> {'problems'} -> [0] -> eigen
;
1401 # This method is renamed __error in dia but not here. If nothing broke
1402 # until now I think we can safely remove it.
1408 # @error = $modelObject -> error;
1410 # Returns the error part specified subproblem.
1411 # TODO: Even though new_error can be specified, they wont be set
1413 my @prob = @
{$self -> problems
};
1414 my @error = @
{$prob[0] -> get_record
('error') -> code
}
1415 if ( defined $prob[0] -> get_record
('error') );
1421 # {{{ extra_data_files
1423 =head2 extra_data_files
1429 $model_object -> extra_data_files( ['extra_data.dta'] );
1431 my $extra_file_name = $model_object -> extra_data_files;
1437 The argument is an unnamed array of strings
1441 If extra_data_files is used without argument the names of any extra
1442 data files connected to the model object is returned. If an argument
1443 is given it must be an array of length equal to the number of problems
1444 in the model. Then the names of the extra data files will be changed
1445 to those in the array.
1449 start extra_data_files
1452 # Sets or retrieves extra_data_file_name on problem level
1453 my $nprobs = scalar @
{$self -> {'problems'}};
1454 if ( defined $parm ) {
1455 if ( ref($parm) eq 'ARRAY' ) {
1456 my @new_file_names = @
{$parm};
1457 # Check that new_file_names and problems match
1458 'debug' -> die( message
=> "model -> extra_data_files: The number of problems $nprobs and" .
1459 " new_file_names " . $#new_file_names+1 . " don't match in ".
1460 $self -> full_name
) unless ( $#new_file_names + 1 == $nprobs );
1461 if ( defined $self -> {'problems'} ) {
1462 for( my $i = 0; $i < $nprobs; $i++ ) {
1463 $self -> {'problems'} -> [$i] -> extra_data_file_name
( $new_file_names[$i] );
1466 'debug' -> die( message
=> "No problems defined in " .
1467 $self -> full_name
);
1470 'debug' -> die(message
=> "Supplied new value is not an array.");
1473 if ( defined $self -> {'problems'} ) {
1474 for( my $i = 0; $i < $nprobs; $i++ ) {
1475 if( defined $self -> {'problems'} -> [$i] -> extra_data_file_name
) {
1476 push ( @file_names ,$self -> {'problems'} -> [$i] -> extra_data_file_name
);
1481 return \
@file_names;
1483 end extra_data_files
1487 # {{{ extra_data_headers
1489 =head2 extra_data_headers
1495 $model_object -> extra_data_headers( [$data_obj] );
1497 my $data_objects = $model_object -> extra_data_headers;
1503 The argument is an unnamed array of arrays of strings.
1507 If extra_data_files is used without argument the headers of any extra
1508 data files connected to the model object is returned. If an argument
1509 is given it must be an array of length equal to the number of problems
1510 in the model. Then the headers of the extra data files will be changed
1511 to those in the array.
1515 start extra_data_headers
1518 # Sets or retrieves extra_data_header on problem level
1519 my $nprobs = scalar @
{$self -> {'problems'}};
1520 if ( defined $parm ) {
1521 if ( ref($parm) eq 'ARRAY' ) {
1522 my @new_headers = @
{$parm};
1523 # Check that new_headers and problems match
1524 'debug' -> die( message
=> "The number of problems $nprobs and".
1525 " new_headers " . $#new_headers+1 . " don't match in ".
1526 $self -> full_name
) unless ( $#new_headers + 1 == $nprobs );
1527 if ( defined $self -> {'problems'} ) {
1528 for( my $i = 0; $i < $nprobs; $i++ ) {
1529 $self -> {'problems'} -> [$i] -> extra_data_header
( $new_headers[$i] );
1532 'debug' -> die( message
=> "No problems defined in " . $self -> full_name
);
1535 'debug' -> die( message
=> "Supplied new value is not an array" );
1538 if ( defined $self -> {'problems'} ) {
1539 for( my $i = 0; $i < $nprobs; $i++ ) {
1540 push ( @headers, $self -> {'problems'} -> [$i] -> extra_data_header
);
1546 end extra_data_headers
1548 # }}} extra_data_headers
1558 my @file_names = $model_object -> input_files();
1568 Returns an two dimensional array with filenames to files that are
1569 necessary for a NONMEM run, i.e. all input files.
1571 The first level of the array is the list of files, the second level is
1572 allways of length two and contains the path and then the file.
1574 Example return value:
1576 [ ['/path/to', 'filename'],
1577 ['/another/path/to', 'another_file'] ]
1584 # TODO: Skip the dataset for now, when I [PP] rewrite the
1585 # "model::copy" routine, I will revisit this.
1588 foreach my $data ( @
{$self -> datas
} ) {
1589 my $filename = $data -> filename
;
1591 #push( @new_data_names, $filename );
1596 if( scalar @
{$self -> msfi_names
()} > 0 ){
1597 foreach my $msfi_files( @
{$self -> msfi_names
()} ){
1598 foreach my $msfi_file( @
{$msfi_files} ){
1599 my ( $dir, $filename ) = OSspecific
::absolute_path
($self -> directory
,
1601 push( @file_names, [$dir, $filename] );
1606 # If we don't have $MSFI we can consider $EST MSFO as input.
1608 foreach my $msfo_files( @
{$self -> msfo_names
()} ){
1609 foreach my $msfo_file( @
{$msfo_files} ){
1610 my ( $dir, $filename ) = OSspecific
::absolute_path
($self -> directory
,
1612 push( @file_names, [$dir, $filename] );
1617 # TODO: as with data files, revisit this when model::copy is
1621 my @problems = @
{$self -> problems
};
1622 for ( my $i = 1; $i <= $#problems + 1; $i++ ) {
1623 my $extra_data = $problems[$i-1] -> extra_data
;
1624 if ( defined $extra_data ) {
1625 my $filename = $extra_data -> filename
;
1627 #push( @, $filename );
1632 # Copy extra fortran files specified in "$SUBROUTINE"
1634 if( defined( $self -> subroutine_files
) ){
1635 foreach my $sub_file ( @
{$self -> subroutine_files
} ){
1636 my ( $dir, $filename ) = OSspecific
::absolute_path
( $self -> directory
,
1638 push( @file_names, [$dir, $filename] );
1642 # Copy extra files the user specified.
1644 if( defined $self -> extra_files
){
1645 foreach my $x_file (@
{$self -> extra_files
}){
1646 my ( $dir, $filename ) = OSspecific
::absolute_path
( $self -> directory
,
1648 push( @file_names, [$dir, $filename] );
1664 my @file_names = $model_object -> output_files();
1674 Returns an array with filenames to files that are produced by a NONMEM
1675 run, i.e. all output files.
1677 Example return value:
1687 push( @file_names, $self -> outputs
-> [0] -> filename
);
1689 if( defined $self -> table_names
){
1690 foreach my $table_files( @
{$self -> table_names
} ){
1691 foreach my $table_file( @
{$table_files} ){
1692 my ($dir, $filename) = OSspecific
::absolute_path
( undef,
1694 push( @file_names, $filename );
1699 if( defined $self -> msfo_names
() ){
1700 foreach my $msfo_files( @
{$self -> msfo_names
()} ){
1701 foreach my $msfo_file( @
{$msfo_files} ){
1702 my ( $dir, $filename ) = OSspecific
::absolute_path
( undef,
1704 push( @file_names, $filename );
1709 if( defined $self -> {'extra_output'} ){
1710 foreach my $extra_out ( @
{$self -> {'extra_output'}} ){
1711 push( @file_names, $extra_out );
1716 my @problems = @
{$self -> problems
};
1717 for( my $i = 0; $i <= $#problems; $i++ ) {
1718 if( $problems[$i-1] -> shrinkage_module
-> enabled
) {
1719 my ( $dir, $eta_filename ) =
1720 OSspecific
::absolute_path
( undef,
1721 $problems[$i] -> shrinkage_module
-> eta_tablename
);
1723 push( @file_names, $eta_filename );
1725 my ( $dir, $wres_filename ) =
1726 OSspecific
::absolute_path
( undef,
1727 $problems[$i] -> shrinkage_module
-> wres_tablename
);
1729 push( @file_names, $wres_filename );
1746 my $factors = $model_object -> factors;
1762 =item problem_number
1766 =item return_occurences
1770 =item unique_in_individual
1778 The following text comes from the documentation of
1779 data::factors. model::factors will call data::factors for the given
1780 problem number in the model object. Also it will take try to find
1781 "column_head" in the $INPUT record instead of the data file header.
1783 Either column (number, starting at 1) or column_head must be
1784 specified. The default behaviour is to return a hash with the factors
1785 as keys referencing arrays with the order numbers (not the ID numbers)
1786 of the individuals that contain this factor.
1788 If unique_in_individual is true (1), the returned hash will contain an
1789 element with key 'Non-unique values found' and value 1 if any
1790 individual contain more than one value in the specified column.
1792 Return occurences will calculate the occurence of each factor
1793 value. Several occurences in one individual counts as one
1794 occurence. The elements of the returned hash will have the factors as
1795 keys and the number of occurences as values.
1801 # Calls <I>factors</I> on the data object of a specified
1802 # problem. See <I>data -> factors</I> for details.
1804 my $extra_data_column;
1805 if ( defined $column_head ) {
1806 # Check normal data object first
1807 my ( $values_ref, $positions_ref ) = $self ->
1808 _get_option_val_pos
( problem_numbers
=> [$problem_number],
1809 name
=> $column_head,
1810 record_name
=> 'input',
1811 global_position
=> 1 );
1812 $column_number = $positions_ref -> [0];
1813 # Next, check extra_data
1814 my $extra_data_headers = $self -> extra_data_headers
;
1815 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
1816 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
1817 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
1820 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
1821 unless ( defined $column_number or defined $extra_data_column );
1823 $column_number = $column;
1825 if ( defined $column_number) {
1826 %factors = %{$self -> {'datas'} -> [$problem_number-1] ->
1827 factors
( column
=> $column_number,
1828 unique_in_individual
=> $unique_in_individual,
1829 return_occurences
=> $return_occurences )};
1831 %factors = %{$self -> {'problems'} -> [$problem_number-1] -> extra_data
1832 -> factors
( column
=> $extra_data_column,
1833 unique_in_individual
=> $unique_in_individual,
1834 return_occurences
=> $return_occurences )};
1849 my $fractions = $model_object -> fractions;
1865 =item problem_number
1869 =item return_occurences
1873 =item ignore_missing
1881 fractions will return the fractions from data::fractions. It will find
1882 "column_head" in the $INPUT record instead of that data header as
1883 data::fractions does.
1889 # Calls <I>fractions</I> on the data object of a specified
1890 # problem. See <I>data -> fractions</I> for details.
1892 my $extra_data_column;
1893 if ( defined $column_head ) {
1894 # Check normal data object first
1895 my ( $values_ref, $positions_ref ) = $self ->
1896 _get_option_val_pos
( problem_numbers
=> [$problem_number],
1897 name
=> $column_head,
1898 record_name
=> 'input',
1899 global_position
=> 1 );
1900 $column_number = $positions_ref -> [0];
1901 # Next, check extra_data
1902 my $extra_data_headers = $self -> extra_data_headers
;
1903 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
1904 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
1905 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
1908 'debug' -> die( "Unknown column \"$column_head\"" )
1909 unless ( defined $column_number or defined $extra_data_column );
1911 $column_number = $column;
1913 if ( defined $column_number) {
1914 %fractions = %{$self -> {'datas'} -> [$problem_number-1] ->
1915 fractions
( column
=> $column_number,
1916 unique_in_individual
=> $unique_in_individual,
1917 ignore_missing
=> $ignore_missing )};
1919 %fractions = %{$self -> {'problems'} -> [$problem_number-1] -> extra_data
1920 -> fractions
( column
=> $extra_data_column,
1921 unique_in_individual
=> $unique_in_individual,
1922 ignore_missing
=> $ignore_missing )};
1937 my $fractions = $model_object -> fractions;
1953 =item problem_number
1957 =item return_occurences
1961 =item ignore_missing
1969 fractions will return the fractions from data::fractions. It will find
1970 "column_head" in the $INPUT record instead of that data header as
1971 data::fractions does.
1977 # Sets or gets the 'fixed' status of a (number of)
1978 # parameter(s). 1 correspond to a parameter being fixed and
1979 # 0 not fixed. The returned parameter is a reference to a
1980 # two-dimensional array, indexed by problems and parameter
1982 # Valid parameter types are 'theta', 'omega' and 'sigma'.
1984 @fixed = @
{ $self -> _init_attr
1985 ( parameter_type
=> $parameter_type,
1986 parameter_numbers
=> \
@parameter_numbers,
1987 problem_numbers
=> \
@problem_numbers,
1988 new_values
=> \
@new_values,
1989 attribute
=> 'fix')};
1995 # {{{ have_missing_data
2003 my $fractions = $model_object -> fractions;
2019 =item problem_number
2023 =item return_occurences
2027 =item ignore_missing
2035 fractions will return the fractions from data::fractions. It will find
2036 "column_head" in the $INPUT record instead of that data header as
2037 data::fractions does.
2041 start have_missing_data
2043 # Calls <I>have_missing_data</I> on the data object of a specified
2044 # problem. See <I>data -> have_missing_data</I> for details.
2046 my $extra_data_column;
2047 if ( defined $column_head ) {
2048 # Check normal data object first
2049 my ( $values_ref, $positions_ref ) = $self ->
2050 _get_option_val_pos
( problem_numbers
=> [$problem_number],
2051 name
=> $column_head,
2052 record_name
=> 'input',
2053 global_position
=> 1 );
2054 $column_number = $positions_ref -> [0];
2055 # Next, check extra_data
2056 my $extra_data_headers = $self -> extra_data_headers
;
2057 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
2058 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
2059 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
2062 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
2063 unless ( defined $column_number or defined $extra_data_column );
2065 $column_number = $column;
2067 if ( defined $column_number) {
2068 $return_value = $self -> {'datas'} -> [$problem_number-1] ->
2069 have_missing_data
( column
=> $column_number );
2071 $return_value = $self -> {'problems'} -> [$problem_number-1] ->
2072 extra_data
-> have_missing_data
( column
=> $extra_data_column );
2075 end have_missing_data
2087 my $fractions = $model_object -> fractions;
2103 =item problem_number
2107 =item return_occurences
2111 =item ignore_missing
2119 fractions will return the fractions from data::fractions. It will find
2120 "column_head" in the $INPUT record instead of that data header as
2121 data::fractions does.
2129 # @idcolumns = @{$modelObject -> idcolumns( problem_numbers => [2,3] );
2131 # idcolumns returns the idcolumn index in the datafile for the
2132 # specified problem.
2135 ( $junk_ref, $col ) = $self ->
2136 _get_option_val_pos
( name
=> 'ID',
2137 record_name
=> 'input',
2138 problem_numbers
=> [$problem_number] );
2140 if ( $problem_number ne 'all' ) {
2156 my $fractions = $model_object -> fractions;
2172 =item problem_number
2176 =item return_occurences
2180 =item ignore_missing
2188 fractions will return the fractions from data::fractions. It will find
2189 "column_head" in the $INPUT record instead of that data header as
2190 data::fractions does.
2198 # @column_numbers = @{$modelObject -> idcolumns( problem_numbers => [2] )};
2200 # idcolumns returns the idcolumn indexes in the datafile for the
2201 # specified problems.
2203 my ( $junk_ref, $col_ref ) = $self ->
2204 _get_option_val_pos
( name
=> 'ID',
2205 record_name
=> 'input',
2206 problem_numbers
=> \
@problem_numbers );
2207 # There should only be one instance of $INPUT and hence we collapse
2208 # the two-dim return from _get_option_pos_val to a one-dim array:
2210 foreach my $prob ( @
{$col_ref} ) {
2211 foreach my $inst ( @
{$prob} ) {
2212 push( @column_numbers, $inst );
2228 $model_object -> ignoresigns( ['#','@'] );
2230 my $ignoresigns = $model_object -> ignoresigns;
2236 The argument is an unnamed array of strings
2240 If ignoresigns is used without argument the string that specifies
2241 which string that is used for comment rows in the data file is
2242 returned. The returned value is an array including the ignore signs
2243 of each problem. If an argument is given it must be an array of
2244 length equal to the number of problems in the model. Then the names of
2245 the extra data files will be changed to those in the array.
2253 # @ignore_signs = @{$modelObject -> ignoresigns( problem_numbers => [2,4] )};
2255 # ignoresigns returns the ignore signs in the datafile for the
2256 # specified problems
2258 foreach my $prob ( @
{$self -> {'problems'}} ) {
2259 my @datarecs = @
{$prob -> datas
};
2260 if ( defined $datarecs[0] ) {
2261 push( @ignore, $datarecs[0] -> ignoresign
);
2263 push( @ignore, '#' );
2267 # print "IGNORE: @ignore\n";
2280 # @ignore_signs = @{$modelObject -> ignore_lists( problem_numbers => [2,4] )};
2282 # ignore_lists returns the ignore signs in the datafile for the
2283 # specified problems
2285 foreach my $prob ( @
{$self -> {'problems'}} ) {
2286 my @datarecs = @
{$prob -> datas
};
2287 if ( defined $datarecs[0] ) {
2288 push( @ignore, $datarecs[0] -> ignore_list
);
2290 push( @ignore, '#' );
2294 # print "IGNORE: @ignore\n";
2309 my $fractions = $model_object -> fractions;
2325 =item problem_number
2329 =item return_occurences
2333 =item ignore_missing
2341 fractions will return the fractions from data::fractions. It will find
2342 "column_head" in the $INPUT record instead of that data header as
2343 data::fractions does.
2351 # @indexArray = @{$modelObject -> indexes( 'parameter_type' => 'omega' )};
2353 # A call to I<indexes> returns the indexes of all parameters
2354 # specified in I<parameter_numbers> from the subproblems
2355 # specified in I<problem_numbers>. The method returns a reference to an array that has
2356 # the same structure as parameter_numbers but for each
2357 # array of numbers is instead an array of indices. The method
2358 # uses a method from the model::problem class to format the
2359 # indices, so here are a few lines from the code comments in
2360 # model/problem.pm that describes the returned value:
2363 # The Indexes method calculates the index for a
2364 # parameter. Off-diagonal elements will get a index 'i_j', where i
2365 # is the row number and j is the column number
2368 unless( $#problem_numbers > 0 ){
2369 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
2371 my @problems = @
{$self -> {'problems'}};
2372 foreach my $i ( @problem_numbers ) {
2373 if ( defined $problems[ $i-1 ] ) {
2375 $problems[ $i-1 ] ->
2376 indexes
( parameter_type
=> $parameter_type,
2377 parameter_numbers
=> $parameter_numbers[ $i-1 ] ) );
2379 'debug' -> die( message
=> "Problem number $i does not exist!" );
2387 # {{{ initial_values
2395 my $fractions = $model_object -> fractions;
2411 =item problem_number
2415 =item return_occurences
2419 =item ignore_missing
2427 fractions will return the fractions from data::fractions. It will find
2428 "column_head" in the $INPUT record instead of that data header as
2429 data::fractions does.
2433 start initial_values
2435 # initial_values either sets or gets the initial values of
2436 # the parameter specified in "parameter_type" for each
2437 # problem specified in problem_numbers. For each element
2438 # in problem_numbers there must be a reference in
2439 # parameter_numbers to an array that specify the indices
2440 # of the parameters in the subproblem for which the initial
2441 # values are set, replaced or retrieved.
2443 # The add_if_absent argument tells the method to add an init
2444 # (theta,omega,sigma) if the parameter number points to a
2445 # non-existing parameter with parameter number one higher
2446 # than the highest presently included. Only applicable if
2447 # new_values are set. Valid parameter types are 'theta',
2448 # 'omega' and 'sigma'.
2450 @initial_values = @
{ $self -> _init_attr
2451 ( parameter_type
=> $parameter_type,
2452 parameter_numbers
=> \
@parameter_numbers,
2453 problem_numbers
=> \
@problem_numbers,
2454 new_values
=> \
@new_values,
2455 attribute
=> 'init',
2456 add_if_absent
=> $add_if_absent )};
2460 # }}} initial_values
2471 my $fractions = $model_object -> fractions;
2487 =item problem_number
2491 =item return_occurences
2495 =item ignore_missing
2503 fractions will return the fractions from data::fractions. It will find
2504 "column_head" in the $INPUT record instead of that data header as
2505 data::fractions does.
2513 # if( $modelObject -> is_option_set( record => 'recordName', name => 'optionName' ) ){
2514 # print "problem_number 1 has option optionName set in record recordName";
2517 # is_option_set checks if an option is set in a given record in given problem.
2519 my ( @problems, @records, @options );
2520 my $accessor = $record.'s';
2521 if ( defined $self -> {'problems'} ) {
2522 @problems = @
{$self -> {'problems'}};
2524 'debug' -> die( message
=> "No problems defined in model" );
2526 unless( defined $problems[$problem_number - 1] ){
2527 'debug' -> warn( level
=> 2,
2528 message
=> "model -> is_option_set: No problem number $problem_number defined in model" );
2529 return 0; # No option can be set if no problem exists.
2532 if ( defined $problems[$problem_number - 1] -> $accessor ) {
2533 @records = @
{$problems[$problem_number - 1] -> $accessor};
2535 'debug' -> warn( level
=> 2,
2536 message
=> "model -> is_option_set: No record $record defined" .
2537 " in problem number $problem_number." );
2541 unless(defined $records[$instance - 1] ){
2542 'debug' -> warn( level
=> 2,
2543 message
=> "model -> is_option_set: No record instance number $instance defined in model." );
2547 if ( defined $records[$instance - 1] -> options
) {
2548 @options = @
{$records[$instance - 1] -> options
};
2550 'debug' -> warn( level
=> 2,
2551 message
=> "No option defined in record: $record in problem number $problem_number." );
2554 foreach my $option ( @options ) {
2555 $found = 1 if ( defined $option and $option -> name
eq $name );
2557 if( index( $name, $option -> name
) > -1 ){
2576 my $fractions = $model_object -> fractions;
2592 =item problem_number
2596 =item return_occurences
2600 =item ignore_missing
2608 fractions will return the fractions from data::fractions. It will find
2609 "column_head" in the $INPUT record instead of that data header as
2610 data::fractions does.
2618 # is_run returns true if the outputobject owned by the
2619 # modelobject has valid outpudata either in memory or on disc.
2620 if( defined $self -> {'outputs'} ){
2621 if( @
{$self -> {'outputs'}}[0] -> have_output
){
2640 my $fractions = $model_object -> fractions;
2656 =item problem_number
2660 =item return_occurences
2664 =item ignore_missing
2672 fractions will return the fractions from data::fractions. It will find
2673 "column_head" in the $INPUT record instead of that data header as
2674 data::fractions does.
2680 my $problems = $self -> {'problems'};
2681 if( defined $problems -> [$problem_number - 1] ) {
2682 my $problem = $problems -> [$problem_number - 1];
2683 # If we don't have an ESTIMATION record we are simulating.
2684 $is_sim = 1 unless( defined $problem -> {'estimations'} and
2685 scalar( @
{$problem-> {'estimations'}} ) > 0 );
2687 # If we have a ONLYSIM option in the simulation record.
2688 $is_sim = 1 if( $self -> is_option_set
( name
=> 'ONLYSIM',
2689 record
=> 'simulation',
2690 problem_number
=> $problem_number ));
2692 # If max evaluations is zero we are simulating
2693 $is_sim = 1 if( defined $self -> maxeval
(problem_numbers
=> [$problem_number]) and
2694 defined $self -> maxeval
(problem_numbers
=> [$problem_number])->[0][0] and
2695 $self -> maxeval
(problem_numbers
=> [$problem_number])->[0][0] == 0 );
2699 # If non of the above is true, we are estimating.
2701 'debug' -> warn( level
=> 1,
2702 message
=> 'Problem nr. $problem_number not defined. Assuming no simulation' );
2718 my $fractions = $model_object -> fractions;
2734 =item problem_number
2738 =item return_occurences
2742 =item ignore_missing
2750 fractions will return the fractions from data::fractions. It will find
2751 "column_head" in the $INPUT record instead of that data header as
2752 data::fractions does.
2758 # lower_bounds either sets or gets the initial values of the
2759 # parameter specified in the argument parameter_type for
2760 # each problem specified in problem_numbers. See L</fixed>.
2762 @lower_bounds = @
{ $self -> _init_attr
2763 ( parameter_type
=> $parameter_type,
2764 parameter_numbers
=> \
@parameter_numbers,
2765 problem_numbers
=> \
@problem_numbers,
2766 new_values
=> \
@new_values,
2767 attribute
=> 'lobnd')};
2781 my $fractions = $model_object -> fractions;
2797 =item problem_number
2801 =item return_occurences
2805 =item ignore_missing
2813 fractions will return the fractions from data::fractions. It will find
2814 "column_head" in the $INPUT record instead of that data header as
2815 data::fractions does.
2823 # @labels = @{$modobj -> labels( parameter_type => 'theta' )};
2825 # This basic usage takes one arguments and returns matched names and
2826 # estimated values of the specified parameter. The parameter_type argument
2827 # is mandatory. It returns the labels of all parameters of type given by
2829 # @labels will be a two-dimensional array:
2830 # [[label1][label2][label3]...]
2832 # $labels -> labels( parameter_type => 'theta',
2833 # problem_numbers => [2,4] );
2835 # To get labels of specific problems, the problem_numbers argument can be used.
2836 # It should be a reference to an array containing the numbers
2837 # of all problems whos labels should be retrieved.
2839 # $modobj -> labels( parameter_type => 'theta',
2840 # problem_numbers => [2,4],
2841 # parameter_numbers => [[1,3][4,6]]);
2843 # The retrieval can be even more specific by using the parameter_numbers
2844 # argument. It should be a reference to a two-dimensional array, where
2845 # the inner arrays holds the numbers of the parameters that should be
2846 # fetched. In the example above, parameters one and three from problem two
2847 # plus parameters four and six from problem four are retrieved.
2849 # $modobj -> labels( parameter_type => 'theta',
2850 # problem_numbers => [2,4],
2851 # parameter_numbers => [[1,3][4,6]],
2854 # To get generic labels for the parameters - e.g. OM1, OM2_1, OM2 etc -
2855 # set the generic argument to 1.
2857 # $modobj -> labels( parameter_type => 'theta',
2858 # problem_numbers => [2],
2859 # parameter_numbers => [[1,3]],
2860 # new_values => [['Volume','Clearance']] );
2862 # The new_values argument can be used to give parameters new labels. In
2863 # the above example, parameters one and three in problem two are renamed
2864 # Volume and Clearance.
2867 my ( @index, $idx );
2868 @labels = @
{ $self -> _init_attr
2869 ( parameter_type
=> $parameter_type,
2870 parameter_numbers
=> \
@parameter_numbers,
2871 problem_numbers
=> \
@problem_numbers,
2872 new_values
=> \
@new_values,
2873 attribute
=> 'label' )};
2875 # foreach my $prl ( @labels ) {
2876 # foreach my $label ( @{$prl} ) {
2877 # print "Label: $label\n";
2882 @index = @
{$self -> indexes
( parameter_type
=> $parameter_type,
2883 parameter_numbers
=> \
@parameter_numbers,
2884 problem_numbers
=> \
@problem_numbers )};
2886 for ( my $i = 0; $i <= $#labels; $i++ ) {
2887 for ( my $j = 0; $j < scalar @
{$labels[$i]}; $j++ ) {
2888 $idx = $index[$i][$j];
2889 $labels[$i][$j] = uc(substr($parameter_type,0,2)).$idx
2890 unless ( defined $labels[$i][$j] and not $generic );
2906 my $fractions = $model_object -> fractions;
2922 =item problem_number
2926 =item return_occurences
2930 =item ignore_missing
2938 fractions will return the fractions from data::fractions. It will find
2939 "column_head" in the $INPUT record instead of that data header as
2940 data::fractions does.
2948 # @maxev = @{$modobj -> maxeval};
2950 # This basic usage takes no arguments and returns the value of the
2951 # MAXEVAL option in the $ESTIMATION record of each problem.
2952 # @maxev will be a two dimensional array:
2953 # [[maxeval_prob1][maxeval_prob2][maxeval_prob3]...]
2955 # $modobj -> maxeval( new_values => [[0],[999]];
2957 # If the new_values argument of maxeval is given, the values of the
2958 # MAXEVAL options will be changed. In this example, MAXEVAL will be
2959 # set to 0 in the first problem and to 999 in the second.
2960 # The number of elements in new_values must match the number of problems
2961 # in the model object $modobj.
2963 # $modobj -> maxeval( new_values => [[0],[999]],
2964 # problem_numbers => [2,4] );
2966 # To set the MAXEVAL of specific problems, the problem_numbers argument can
2967 # be used. It should be a reference to an array containing the numbers
2968 # of all problems where the MAXEVAL should be changed or retrieved.
2969 # If specified, the size of new_values must be the same as the size
2970 # of problem_numbers.
2975 my ( $val_ref, $junk ) = $self ->
2976 _option_val_pos
( name
=> 'MAX',
2977 record_name
=> 'estimation',
2978 problem_numbers
=> \
@problem_numbers,
2979 new_values
=> \
@new_values,
2980 exact_match
=> $exact_match );
2981 @values = @
{$val_ref};
2995 my $fractions = $model_object -> fractions;
3011 =item problem_number
3015 =item return_occurences
3019 =item ignore_missing
3027 fractions will return the fractions from data::fractions. It will find
3028 "column_head" in the $INPUT record instead of that data header as
3029 data::fractions does.
3035 # Calls <I>median</I> on the data object of a specified
3036 # problem. See <I>data -> median</I> for details.
3038 my $extra_data_column;
3039 if ( defined $column_head ) {
3040 # Check normal data object first
3041 my ( $values_ref, $positions_ref ) = $self ->
3042 _get_option_val_pos
( problem_numbers
=> [$problem_number],
3043 name
=> $column_head,
3044 record_name
=> 'input',
3045 global_position
=> 1 );
3046 $column_number = $positions_ref -> [0];
3047 if ( not defined $column_number ) {
3048 # Next, check extra_data
3049 my $extra_data_headers = $self -> extra_data_headers
;
3050 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
3051 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
3052 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
3056 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
3057 unless ( defined $column_number or defined $extra_data_column );
3059 $column_number = $column;
3062 if ( defined $column_number) {
3063 $median = $self -> {'datas'} -> [$problem_number-1] ->
3064 median
( column
=> $column_number,
3065 unique_in_individual
=> $unique_in_individual );
3067 $median = $self -> {'problems'} -> [$problem_number-1] -> extra_data
->
3068 median
( column
=> $extra_data_column,
3069 unique_in_individual
=> $unique_in_individual );
3084 my $fractions = $model_object -> fractions;
3100 =item problem_number
3104 =item return_occurences
3108 =item ignore_missing
3116 fractions will return the fractions from data::fractions. It will find
3117 "column_head" in the $INPUT record instead of that data header as
3118 data::fractions does.
3124 # Calls <I>max</I> on the data object of a specified
3125 # problem. See <I>data -> max</I> for details.
3127 my $extra_data_column;
3128 if ( defined $column_head ) {
3129 # Check normal data object first
3130 my ( $values_ref, $positions_ref ) = $self ->
3131 _get_option_val_pos
( problem_numbers
=> [$problem_number],
3132 name
=> $column_head,
3133 record_name
=> 'input',
3134 global_position
=> 1 );
3135 $column_number = $positions_ref -> [0];
3136 if ( not defined $column_number ) {
3137 # Next, check extra_data
3138 my $extra_data_headers = $self -> extra_data_headers
;
3139 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
3140 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
3141 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
3145 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
3146 unless ( defined $column_number or defined $extra_data_column );
3148 $column_number = $column;
3151 if ( defined $column_number) {
3152 $max = $self -> {'datas'} -> [$problem_number-1] ->
3153 max
( column
=> $column_number );
3155 $max = $self -> {'problems'} -> [$problem_number-1] -> extra_data
->
3156 max
( column
=> $extra_data_column );
3171 my $fractions = $model_object -> fractions;
3187 =item problem_number
3191 =item return_occurences
3195 =item ignore_missing
3203 fractions will return the fractions from data::fractions. It will find
3204 "column_head" in the $INPUT record instead of that data header as
3205 data::fractions does.
3211 # Calls <I>min</I> on the data object of a specified
3212 # problem. See <I>data -> min</I> for details.
3214 my $extra_data_column;
3215 if ( defined $column_head ) {
3216 # Check normal data object first
3217 my ( $values_ref, $positions_ref ) = $self ->
3218 _get_option_val_pos
( problem_numbers
=> [$problem_number],
3219 name
=> $column_head,
3220 record_name
=> 'input',
3221 global_position
=> 1 );
3222 $column_number = $positions_ref -> [0];
3223 if ( not defined $column_number ) {
3224 # Next, check extra_data
3225 my $extra_data_headers = $self -> extra_data_headers
;
3226 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
3227 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
3228 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
3232 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
3233 unless ( defined $column_number or defined $extra_data_column );
3235 $column_number = $column;
3238 if ( defined $column_number) {
3239 $min = $self -> {'datas'} -> [$problem_number-1] ->
3240 min
( column
=> $column_number );
3242 $min = $self -> {'problems'} -> [$problem_number-1] -> extra_data
->
3243 min
( column
=> $extra_data_column );
3258 my $fractions = $model_object -> fractions;
3274 =item problem_number
3278 =item return_occurences
3282 =item ignore_missing
3290 fractions will return the fractions from data::fractions. It will find
3291 "column_head" in the $INPUT record instead of that data header as
3292 data::fractions does.
3300 # @name_val = @{$modobj -> name_val( parameter_type => 'theta' )};
3302 # This basic usage takes one arguments and returns matched names and
3303 # estimated values of the specified parameter. The parameter_type argument
3305 # The names are taken from
3306 # the labels of the parameters (se the labels method for specifications of
3307 # default labels) and the values are aquired from the output object bound
3308 # to the model object. If no output exists, the name_val method returns
3310 # @name_val will be a two-dimensional array of references to hashes using
3311 # the names from each problem as keys:
3312 # [[ref to hash1 ][ref to hash2][ref to hash3]...]
3314 # $modobj -> name_val( parameter_type => 'theta',
3315 # problem_numbers => [2,4] );
3317 # To get matched names and values of specific problems, the problem_numbers argument
3318 # can be used. It should be a reference to an array containing the numbers
3319 # of all problems whos names and values should be retrieved.
3321 # $modobj -> name_val( parameter_type => 'theta',
3322 # problem_numbers => [2,4],
3323 # parameter_numbers => [[1,3][4,6]]);
3325 # The retrieval can be even more specific by using the parameter_numbers
3326 # argument. It should be a reference to a two-dimensional array, where
3327 # the inner arrays holds the numbers of the parameters that should be
3328 # fetched. In the example above, parameters one and three from problem two
3329 # plus parameters four and six from problem four are retrieved.
3332 unless( $#problem_numbers > 0 ){
3333 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
3335 my @names = @
{$self -> labels
( parameter_type
=> $parameter_type,
3336 parameter_numbers
=> \
@parameter_numbers,
3337 problem_numbers
=> \
@problem_numbers )};
3339 if ( defined $self -> outputs
-> [0] ) {
3340 my $accessor = $parameter_type.'s';
3341 @values = @
{$self -> outputs
-> [0] ->
3342 $accessor( problems
=> \
@problem_numbers,
3343 parameter_numbers
=> \
@parameter_numbers )};
3344 # my @problems = @{$self -> {'problems'}};
3345 # foreach my $i ( @problem_numbers ) {
3346 # if ( defined $problems[ $i-1 ] ) {
3347 # my $pn_ref = $#parameter_numbers >= 0 ? \@{$parameter_numbers[ $i-1 ]} : [];
3348 # push( @names_values,
3349 # $problems[ $i-1 ] ->
3350 # name_val( parameter_type => $parameter_type,
3351 # parameter_numbers => $pn_ref ) );
3353 # die "Model -> name_val: Problem number $i does not exist!\n";
3357 # if ( scalar @{$self -> {'outputs'}} > 0 ) {
3358 # my $outobj = $self -> {'outputs'} -> [0];
3361 'debug' -> die( message
=> "The number of problems retrieved from the model" .
3362 " do not match the ones retrived from the output" ) unless( $#names == $#values );
3363 for( my $i = 0; $i <= $#names; $i++ ) {
3364 'debug' -> die( message
=> "Problem " . $i+1 .
3365 " The number of parameters retrieved from the model (".scalar @
{$names[$i]}.
3366 ") do not match the ones retrived from the output (".
3367 scalar @
{$values[$i][0]}.")" )
3368 unless( scalar @
{$names[$i]} == scalar @
{$values[$i][0]} );
3370 for( my $j = 0; $j < scalar @
{$values[$i]}; $j++ ){
3372 for( my $k = 0; $k < scalar @
{$names[$i]}; $k++ ){
3373 $nv{$names[$i][$k]} = $values[$i][$j][$k];
3375 push( @prob_nv, \
%nv );
3377 push( @names_values, \
@prob_nv );
3392 my $fractions = $model_object -> fractions;
3408 =item problem_number
3412 =item return_occurences
3416 =item ignore_missing
3424 fractions will return the fractions from data::fractions. It will find
3425 "column_head" in the $INPUT record instead of that data header as
3426 data::fractions does.
3432 # nproblems returns the number of problems in the modelobject.
3434 $number_of_problem = scalar @
{$self -> {'problems'}};
3448 my $fractions = $model_object -> fractions;
3464 =item problem_number
3468 =item return_occurences
3472 =item ignore_missing
3480 fractions will return the fractions from data::fractions. It will find
3481 "column_head" in the $INPUT record instead of that data header as
3482 data::fractions does.
3488 # returns the number of thetas in the model for the given
3490 $nthetas = $self -> _parameter_count
( 'record' => 'theta', 'problem_number' => $problem_number );
3504 my $fractions = $model_object -> fractions;
3520 =item problem_number
3524 =item return_occurences
3528 =item ignore_missing
3536 fractions will return the fractions from data::fractions. It will find
3537 "column_head" in the $INPUT record instead of that data header as
3538 data::fractions does.
3544 # returns the number of omegas in the model for the given
3546 # $nomegas = $self -> _parameter_count( 'record' => 'omega', 'problem_number' => $problem_number );
3547 unless( $#problem_numbers >= 0 ){
3548 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
3551 my @problems = @
{$self -> {'problems'}};
3552 foreach my $i ( @problem_numbers ) {
3553 if ( defined $problems[ $i-1 ] ) {
3554 push( @nomegas, $problems[ $i-1 ] -> nomegas
( with_correlations
=> $with_correlations ));
3556 'debug' -> die( "Problem number $i does not exist." );
3572 my $fractions = $model_object -> fractions;
3588 =item problem_number
3592 =item return_occurences
3596 =item ignore_missing
3604 fractions will return the fractions from data::fractions. It will find
3605 "column_head" in the $INPUT record instead of that data header as
3606 data::fractions does.
3612 # returns the number of sigmas in the model for the given problem number.
3614 # $nsigmas = $self -> _parameter_count( 'record' => 'sigma', 'problem_number' => $problem_number );
3616 unless( $#problem_numbers >= 0 ){
3617 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
3620 my @problems = @
{$self -> {'problems'}};
3621 foreach my $i ( @problem_numbers ) {
3622 if ( defined $problems[ $i-1 ] ) {
3623 push( @nsigmas, $problems[ $i-1 ] -> nsigmas
( with_correlations
=> $with_correlations ));
3625 'debug' -> die( "Problem number $i does not exist." );
3641 my $fractions = $model_object -> fractions;
3657 =item problem_number
3661 =item return_occurences
3665 =item ignore_missing
3673 fractions will return the fractions from data::fractions. It will find
3674 "column_head" in the $INPUT record instead of that data header as
3675 data::fractions does.
3683 # This method is a (partially) automatically generated accessor for the
3684 # outputfile attribute of the model class. Since no named argument is needed
3685 # for accessors, the two possible ways of calling outputfile are:
3687 # $modelObject -> outputfile( 'newfilename.lst' );
3689 # $outputfilename = $modelObject -> outputfile;
3691 # The first alternative sets a new name for the output file, and the second
3692 # retrieves the value.
3694 # The extra feature for this accessor, compared to other accessors, is that
3695 # if a new name is given, the accessor tries to create a new output object
3698 if( defined $parm ) {
3699 $self -> {'outputs'} =
3701 new
( filename
=> $parm,
3702 ignore_missing_files
=> ( $self -> ignore_missing_files
() || $self -> ignore_missing_output_files
() ),
3703 target
=> $self -> target
(),
3704 model_id
=> $self -> model_id
() ) ];
3719 my $fractions = $model_object -> fractions;
3735 =item problem_number
3739 =item return_occurences
3743 =item ignore_missing
3751 fractions will return the fractions from data::fractions. It will find
3752 "column_head" in the $INPUT record instead of that data header as
3753 data::fractions does.
3759 # sets or gets the pk code for a given problem in the
3760 # model object. The new_pk argument should be an array where
3761 # each element contains a row of a valid NONMEM $PK block,
3763 my @prob = @
{$self -> problems
};
3765 unless( defined $prob[$problem_number - 1] ){
3766 'debug' -> die( message
=> "Problem number $problem_number does not exist" );
3769 my $pks = $prob[$problem_number - 1] -> pks
;
3770 if( scalar @new_pk > 0 ) {
3771 if( defined $pks and scalar @
{$pks} > 0 ){
3772 $prob[$problem_number - 1] -> pks
-> [0] -> code
(\
@new_pk);
3774 'debug' -> die( message
=> "No \$PK record" );
3777 if ( defined $pks and scalar @
{$pks} > 0 ) {
3778 @pk = @
{$prob[$problem_number - 1] -> pks
-> [0] -> code
};
3794 my $fractions = $model_object -> fractions;
3810 =item problem_number
3814 =item return_occurences
3818 =item ignore_missing
3826 fractions will return the fractions from data::fractions. It will find
3827 "column_head" in the $INPUT record instead of that data header as
3828 data::fractions does.
3834 # Sets or gets the pred code for a given problem in the model
3835 # object. See L</pk> for details.
3836 my @prob = @
{$self -> problems
};
3838 unless( defined $prob[$problem_number - 1] ){
3839 'debug' -> die( message
=> "problem number $problem_number does not exist" );
3842 if( scalar @new_pred > 0 ) {
3843 if( defined $prob[$problem_number - 1] -> preds
){
3844 $prob[$problem_number - 1] -> preds
-> [0] -> code
(\
@new_pred);
3846 'debug' -> die( message
=> "No \$PRED record" );
3849 if ( defined $prob[$problem_number - 1] -> preds
) {
3850 @pred = @
{$prob[$problem_number - 1] -> preds
-> [0] -> code
};
3852 'debug' -> die( message
=> "No \$PRED record" );
3868 my $fractions = $model_object -> fractions;
3884 =item problem_number
3888 =item return_occurences
3892 =item ignore_missing
3900 fractions will return the fractions from data::fractions. It will find
3901 "column_head" in the $INPUT record instead of that data header as
3902 data::fractions does.
3908 # Prints the formatted model to standard out.
3911 foreach my $problem ( @
{$self -> {'problems'}} ) {
3912 foreach my $line (@
{$problem-> _format_problem
}){
3921 # {{{ problem_structure
3923 start problem_structure
3925 my ( $val, $pos ) = $self -> _option_val_pos
( record_name
=> 'simulation',
3926 name
=> 'SUBPROBLEMS' );
3927 if( defined $val ) {
3929 for( my $i = 0; $i <= $#vals; $i++ ) {
3930 if( defined $vals[$i] ) {
3931 if( scalar @
{$vals[$i]} > 0 ) {
3932 $subproblems[$i] = $vals[$i][0];
3934 $subproblems[$i] = 1;
3937 $subproblems[$i] = 1;
3942 end problem_structure
3944 # }}} problem_structure
3946 # {{{ randomize_inits
3954 my $fractions = $model_object -> fractions;
3970 =item problem_number
3974 =item return_occurences
3978 =item ignore_missing
3986 fractions will return the fractions from data::fractions. It will find
3987 "column_head" in the $INPUT record instead of that data header as
3988 data::fractions does.
3992 start randomize_inits
3994 foreach my $prob ( @
{$self -> {'problems'}} ) {
3995 $prob -> set_random_inits
( degree
=> $degree );
4010 my $fractions = $model_object -> fractions;
4026 =item problem_number
4030 =item return_occurences
4034 =item ignore_missing
4042 fractions will return the fractions from data::fractions. It will find
4043 "column_head" in the $INPUT record instead of that data header as
4044 data::fractions does.
4050 # If the argument new_data is given, record sets new_data in
4051 # the model objects member specified with record_name. The
4052 # format of new_data is an array of strings, where each
4053 # element corresponds to a line of code as it would have
4054 # looked like in a valid NONMEM modelfile. If new_data is left
4055 # undefined, record returns lines of code belonging to the
4056 # record specified by record_name in a format that is valid in
4057 # a NONMEM modelfile.
4059 my @problems = @
{$self -> {'problems'}};
4062 if ( defined $problems[ $problem_number - 1 ] ) {
4063 if ( scalar(@new_data) > 0 ){
4064 my $rec_class = "model::problem::$record_name";
4065 my $record = $rec_class -> new
('record_arr' => \
@new_data );
4067 $record_name .= 's';
4068 $records = $problems[ $problem_number - 1 ] -> {$record_name};
4069 foreach my $record( @
{$records} ){
4070 push(@data, $record -> _format_record
);
4087 my $fractions = $model_object -> fractions;
4103 =item problem_number
4107 =item return_occurences
4111 =item ignore_missing
4119 fractions will return the fractions from data::fractions. It will find
4120 "column_head" in the $INPUT record instead of that data header as
4121 data::fractions does.
4129 # $model -> remove_inits( type => 'theta',
4130 # indexes => [1,2,5,6] )
4133 # In all cases the type must be set to theta. Removing Omegas in
4134 # Sigmas is not allowed, (If need that feature, send us a
4135 # mail). In the above example the thetas 1, 2, 5 and 6 will be
4136 # removed from the modelfile. Notice that this alters the theta
4137 # numbering, so if you later decide that theta number 7 must be
4138 # removed as well, you must calculate its new position in the
4139 # file. In this case the new number would be 3. Also notice that
4140 # numbering starts with 1.
4142 # $model -> remove_inits( type => 'theta',
4143 # labels => ['V', 'CL'] )
4146 # If you have specified labels in you modelfiles(a label is
4147 # string inside a comment on the same row as the theta) you can
4148 # specify an array with labels, and the corresponding theta, if
4149 # it exists, will be removed. This is a much better approach
4150 # since you don't need to know where in order the theta you wish
4151 # to remove appears. If you specify both labels and indexes, the
4152 # indexes will be ignored.
4154 'debug' -> die( message
=> 'does not have the functionality for removing $OMEGA or $SIGMA options yet' )
4155 if ( $type eq 'omega' or $type eq 'sigma' );
4156 my $accessor = $type.'s';
4158 # First pick out a referens to the theta records array.
4159 my $inits_ref = $self -> problems
-> [$problem_number -1] -> $accessor;
4161 # If we have any thetas at all:
4162 if ( defined $inits_ref ) {
4163 my @inits = @
{$inits_ref};
4165 # If labels are specified, we translate the labels into
4167 if ( scalar @labels > 0 ) {
4170 # Loop over theta records
4171 foreach my $init ( @inits ) {
4172 # Loop over the individual thetas inside
4173 foreach my $option ( @
{$init -> options
} ) {
4174 # Loop over all given labels.
4175 foreach my $label ( @labels ) {
4176 # Push the index number if a given label match the
4178 push( @indexes, $i ) if ( $option -> label
eq $label);
4180 # $i is the count of thetas so far
4186 # We don't really remove thetas, we do a loop over all thetas
4187 # and recording which we like to keep. We do that by selecting
4188 # an index, from @indexes, that shall be removed and loop over
4189 # the thetas, all thetas that doesn't match the index are
4190 # stored in @keep_options. When we find a theta that matches,
4191 # we pick a new index and continue the loop. So by makeing
4192 # sure that @indexes is sorted, we only need to loop over the
4195 @indexes = sort {$a <=> $b} @indexes;
4201 # Loop over all records
4202 RECORD_LOOP
: foreach my $record ( @inits ){
4203 my @keep_options = ();
4204 # Loop over all thetas
4205 foreach my $option ( @
{$record -> options
} ) {
4206 if( $indexes[ $index ] == $nr_options ){
4207 # If a theta matches an index, we take the next index
4208 # and forget the theta.
4209 unless( $index > $#indexes ){
4213 # Otherwise we rember it.
4214 push(@keep_options,$option);
4218 if( scalar(@keep_options) > 0 ){
4219 # If we remember some thetas, we must also remember the
4220 # record which they are in.
4221 $record -> options
( \
@keep_options );
4222 push( @keep_records, $record );
4226 # Set the all kept thetas back into the modelobject.
4227 @
{$inits_ref} = @keep_records;
4230 'debug' -> die( message
=> "No init of type $type defined" );
4245 my $fractions = $model_object -> fractions;
4261 =item problem_number
4265 =item return_occurences
4269 =item ignore_missing
4277 fractions will return the fractions from data::fractions. It will find
4278 "column_head" in the $INPUT record instead of that data header as
4279 data::fractions does.
4285 # restore_inits brings back initial values previously stored
4286 # using store_inits. This method pair allows a user to store
4287 # the currents initial values in a backup, replace them with
4288 # temporary values and later restore them.
4290 if ( defined $self -> {'problems'} ) {
4291 foreach my $problem ( @
{$self -> {'problems'}} ){
4292 $problem -> restore_inits
;
4308 my $fractions = $model_object -> fractions;
4324 =item problem_number
4328 =item return_occurences
4332 =item ignore_missing
4340 fractions will return the fractions from data::fractions. It will find
4341 "column_head" in the $INPUT record instead of that data header as
4342 data::fractions does.
4348 # store_inits stores initial values that can later be
4349 # brought back using restore_inits. See L</restore_inits>.
4351 if ( defined $self -> {'problems'} ) {
4352 foreach my $problem ( @
{$self -> {'problems'}} ){
4353 $problem -> store_inits
;
4365 # Synchronize checks the I<synced> object attribute to see
4366 # if the model is in sync with its corresponding file, given
4367 # by the objetc attribute I<filename>. If not, it checks if
4368 # the model contains any defined problems and if it does, it
4369 # writes the formatted model to disk, overwriting any
4370 # existing file of name I<filename>. If no problem is
4371 # defined, synchronize tries to parse the file I<filename>
4372 # and set the object internals to match it.
4373 unless( $self -> {'synced'} ){
4374 if( defined $self -> {'problems'} and
4375 scalar @
{$self -> {'problems'}} > 0 ){
4378 if( -e
$self -> full_name
){
4379 $self -> _read_problems
;
4385 $self -> {'synced'} = 1;
4393 # synchronizes the object with the file on disk and empties
4394 # most of the objects attributes to save memory.
4395 if( defined $self -> {'problems'} and
4396 ( !$self -> {'synced'} or $force ) ) {
4399 $self -> {'problems'} = undef;
4400 $self -> {'synced'} = 0;
4408 if ( $parm eq 'disk' ) {
4409 $self -> {'target'} = 'disk';
4411 } elsif ( $parm eq 'mem' and $self -> {'target'} eq 'disk' ) {
4412 $self -> {'target'} = 'mem';
4413 $self -> synchronize
;
4427 my $msfi_names_ref = $model_object -> msfi_names;
4439 =item problem_numbers
4443 =item ignore_missing_files
4451 msfi_names will return the names of all MSFI= statements in the
4452 $ESTIMATION records in all problems.
4459 # @msfiNames = @{$modobj -> msfi_names};
4463 # $msfiNamesRef = $modobj -> msfi_names;
4464 # @msfiNames = @{$msfiNamesRef} if (defined $msfiNamesRef);
4466 # This basic usage takes no arguments and returns the value of
4467 # the MSFI option in the $ESTIMATION NONMEM record of each
4468 # problem. @msfiNames will be a two-dimensional array:
4470 # [[msfiName_prob1],[msfiName_prob2],[msfiName_prob3]...]
4474 if ( defined $self -> problems
() ) {
4475 @problems = @
{$self -> problems
()};
4477 'debug' -> die( message
=> "No problems defined in model" );
4480 if( scalar @new_names > 0 ) {
4482 foreach my $prob ( @problems ) {
4483 $prob -> remove_records
( type
=> 'msfi' );
4484 if( defined $new_names[$i] ) {
4485 $prob -> add_records
( type
=> 'msfi',
4486 record_strings
=> [$new_names[$i]] );
4490 foreach my $prob ( @problems ) {
4491 if ( defined $prob -> msfis
() ) {
4492 my @instances = @
{$prob -> msfis
()};
4494 foreach my $instance ( @instances ) {
4496 if ( defined $instance -> options
() ) {
4497 @options = @
{$instance -> options
()};
4499 if ( defined $options[0] ) {
4500 push( @prob_names, $options[0] -> name
);
4502 push( @prob_names, undef );
4505 push( @names, \
@prob_names );
4522 my $msfo_names_ref = $model_object -> msfo_names;
4534 =item problem_numbers
4538 =item ignore_missing_files
4546 msfo_names will return the names of all MSFO= statements in the
4547 $ESTIMATION records in all problems.
4554 # @msfoNames = @{$modobj -> msfo_names};
4558 # $msfoNamesRef = $modobj -> msfo_names;
4559 # @msfoNames = @{$msfoNamesRef} if (defined $msfoNamesRef);
4561 # This basic usage takes no arguments and returns the value of
4562 # the MSFO option in the $ESTIMATION NONMEM record of each
4563 # problem. @msfoNames will be an array:
4565 # [msfoName_prob1,msfoName_prob2,msfoName_prob3...]
4568 # If the I<new_names> argument of msfo_names is given, the
4569 # values of the MSFO options will be changed.
4571 # To set the MSFO of specific problems, the I<problem_numbers>
4572 # argument can be used. It should be a reference to an array
4573 # containing the numbers of all problems where the FILE should
4574 # be changed or retrieved. If specified, the size of
4575 # I<new_names> must be the same as the size of
4576 # I<problem_numbers>.
4578 my ( $name_ref, $junk ) = $self ->
4579 _option_val_pos
( name
=> 'MSFO',
4580 record_name
=> 'estimation',
4581 problem_numbers
=> \
@problem_numbers,
4582 new_values
=> \
@new_names );
4585 my ( $nonp_name_ref, $junk ) = $self ->
4586 _option_val_pos
( name
=> 'MSFO',
4587 record_name
=> 'nonparametric',
4588 problem_numbers
=> \
@problem_numbers,
4589 new_values
=> \
@new_names );
4591 if( scalar( @
{$name_ref -> [0]} > 0 ) ){
4592 push( @names, @
{$name_ref} );
4595 if( scalar( @
{$nonp_name_ref -> [0]} > 0 ) ){
4596 push( @names, @
{$nonp_name_ref} );
4611 my $fractions = $model_object -> fractions;
4627 =item problem_number
4631 =item return_occurences
4635 =item ignore_missing
4643 fractions will return the fractions from data::fractions. It will find
4644 "column_head" in the $INPUT record instead of that data header as
4645 data::fractions does.
4653 # @tableNames = @{$modobj -> table_names};
4655 # This basic usage takes no arguments and returns the value of
4656 # the FILE option in the $TABLE NONMEM record of each
4657 # problem. @tableNames will be a two dimensional array:
4659 # [[tableName_prob1][tableName_prob2][tableName_prob3]...]
4662 # If the I<new_names> argument of table_names is given, the
4663 # values of the FILE options will be changed.
4665 # To set the FILE of specific problems, the I<problem_numbers>
4666 # argument can be used. It should be a reference to an array
4667 # containing the numbers of all problems where the FILE should
4668 # be changed or retrieved. If specified, the size of
4669 # I<new_names> must be the same as the size of
4670 # I<problem_numbers>.
4672 # The I<ignore_missing_files> boolean argument can be used to
4673 # set names of table that does not exist yet (e.g. before a
4674 # run has been performed).
4676 my ( $name_ref, $junk ) = $self ->
4677 _option_val_pos
( name
=> 'FILE',
4678 record_name
=> 'table',
4679 problem_numbers
=> \
@problem_numbers,
4680 new_values
=> \
@new_names );
4681 if ( $#new_names >= 0 ) {
4682 my @problems = @
{$self -> {'problems'}};
4683 unless( $#problem_numbers > 0 ){
4684 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
4686 foreach my $i ( @problem_numbers ) {
4687 $problems[$i-1] -> _read_table_files
( ignore_missing_files
=> $ignore_missing_files || $self -> {'ignore_missing_output_files'});
4690 @names = @
{$name_ref};
4704 my $fractions = $model_object -> fractions;
4720 =item problem_number
4724 =item return_occurences
4728 =item ignore_missing
4736 fractions will return the fractions from data::fractions. It will find
4737 "column_head" in the $INPUT record instead of that data header as
4738 data::fractions does.
4746 # @table_files = @{$modobj -> table_files};
4748 # This basic usage takes no arguments and returns the table
4749 # files objects for all problems. @table_files will be a
4750 # two dimensional array:
4752 # [[table_file_object_prob1][table_file_object_prob2]...]
4755 # To retrieve the table file objects from specific problems,
4756 # the I<problem_numbers> argument can be used. It should be
4757 # a reference to an array containing the numbers of all
4758 # problems from which the table file objects should be
4761 unless( $#problem_numbers > 0 ){
4762 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
4764 my @problems = @
{$self -> {'problems'}};
4765 foreach my $i ( @problem_numbers ) {
4766 if ( defined $problems[ $i-1 ] ) {
4767 push( @table_files, $problems[$i-1] -> table_files
);
4769 'debug' -> die( message
=> "Problem number $i does not exist!" );
4785 my $fractions = $model_object -> fractions;
4801 =item problem_number
4805 =item return_occurences
4809 =item ignore_missing
4817 fractions will return the fractions from data::fractions. It will find
4818 "column_head" in the $INPUT record instead of that data header as
4819 data::fractions does.
4825 # Sets or gets the units of a (number of) parameter(s). The
4826 # unit is not a proper NONMEM syntax but is recognized by
4827 # the PsN model class. A unit (and a label) can be specified
4828 # as a comments after a parameter definition. e.g.:
4830 # $THETA (0,13.2,100) ; MTT; h
4832 # which will give this theta the label I<MTT> and unit I<h>.
4833 @units = @
{ $self -> _init_attr
( parameter_type
=> $parameter_type,
4834 parameter_numbers
=> \
@parameter_numbers,
4835 problem_numbers
=> \
@problem_numbers,
4836 new_values
=> \
@new_values,
4852 my $fractions = $model_object -> fractions;
4868 =item problem_number
4872 =item return_occurences
4876 =item ignore_missing
4884 fractions will return the fractions from data::fractions. It will find
4885 "column_head" in the $INPUT record instead of that data header as
4886 data::fractions does.
4894 # $modobj -> update_inits ( from_output => $outobj );
4898 # $modobj -> update_inits ( from_output_file => $outfile );
4900 # This basic usage takes the parameter estimates from the
4901 # output object I<$outobj> or from the output file I<$outfile>
4902 # and updates the initial estimates in the model object
4903 # I<$modobj>. The number of problems and parameters must be
4904 # the same in the model and output objects. If there exist
4905 # more than one subproblem per problem in the output object,
4906 # only the estimates from the first subproblem will be
4909 # $modobj -> update_inits ( from_output => $outobj,
4910 # ignore_missing_parameters => 1 );
4912 # If the ignore_missing_parameters argument is set to 1, the number of
4913 # parameters in the model and output objects do not need to match. The
4914 # parameters that exist in both objects are used for the update of the
4917 # $modobj -> update_inits ( from_output => $outobj,
4918 # from_model => $from_modobj );
4920 # If the from_model argument is given, update_inits tries to match the
4921 # parameter names (labels) given in $from_modobj and $modobj and
4922 # and thereafter updating the $modobj object. See L</units> and L</labels>.
4925 my ( %labels, @own_labels, @from_labels );
4926 'debug' -> die( message
=> "No output object defined and" .
4927 " no output object found through the model object specified." )
4928 unless ( ( defined $from_model and
4929 ( defined $from_model -> outputs
and
4930 defined @
{$from_model -> outputs
}[0] ) ) or
4931 defined $from_output or
4932 defined $from_output_file );
4933 if ( defined $from_output ) {
4934 'debug' -> warn( level
=> 2,
4935 message
=> "using output object ".
4936 "specified as argument\n" );
4937 } elsif ( defined $from_output_file ) {
4938 $from_output = output
-> new
( filename
=> $from_output_file );
4940 $from_output = @
{$from_model -> outputs
}[0];
4944 if( $update_thetas ){
4945 push( @params, 'theta' );
4947 if( $update_omegas ) {
4948 push( @params, 'omega' );
4950 if( $update_sigmas ) {
4951 push( @params, 'sigma' );
4954 foreach my $param ( @params ) {
4955 # Get own labels and from labels
4956 if ( defined $from_model ) {
4957 @own_labels = @
{$self -> labels
( parameter_type
=> $param )};
4959 @from_labels = @
{$from_model -> labels
( parameter_type
=> $param )};
4960 'debug' -> die( message
=> "The number of problems are not the same in from-model ".
4961 $from_model -> full_name
." (".
4962 ($#from_labels+1).")".
4963 " and the model to be updated ".
4964 $self -> full_name
." (".
4965 ($#own_labels+1).")" ) unless ( $#own_labels == $#from_labels );
4967 @own_labels = @
{$self -> labels
( parameter_type
=> $param,
4969 @from_labels = @
{$from_output -> labels
( parameter_type
=> $param )};
4970 'debug' -> die( message
=> "The number of problems are not the same in from-output ".
4971 $from_output -> full_name
." (".
4972 ($#from_labels+1).")".
4973 " and the model to be updated ".
4974 $self -> full_name
." (".
4975 ($#own_labels+1).")" ) unless ( $#own_labels == $#from_labels );
4978 # Loop over the problems:
4979 my $accessor = $param.'s';
4980 # Since initial estimates are specified on the problem level and not on
4981 # the subproblem level we use the estimates from the outputs first subproblem
4982 my @from_values = @
{$from_output -> $accessor ( subproblems
=> [1] )};
4983 # {{{ Omega and Sigma update section
4985 # The functionality that has been commented out because it
4986 # fails when omegas are zero. This functionality should be
4987 # moved to output::problem::subproblem (2005-02-09) TODO
4989 # if ($param eq 'omega' or $param eq 'sigma')
4991 # #print "FL: ", Dumper @from_labels;
4992 # #print "OL: ", Dumper @own_labels;
4993 # print "FV: $param Before " . Dumper(@from_values) . "\n";
4994 # #Fix omegas and sigmas so that the correlation between elements <=1
4995 # my $raw_accessor = "raw_" . $accessor;
4996 # my @raw_from_values = @{$from_output -> $raw_accessor(subproblems => [1])};
4998 # for (my $a=0; $a<scalar(@from_values); $a++)
5000 # my $prob_values = $from_values[$a];
5001 # my $raw_prob_values = $raw_from_values[$a];
5002 # for (my $b=0; $b<scalar(@{$prob_values}); $b++)
5004 # my $values = $prob_values->[$b];
5005 # my $raw_values = $raw_prob_values->[$b];
5007 # #Find out the n*n-matrix size (pq-formula)
5008 # my $n = int(sqrt(1/4+scalar(@{$raw_values})*2)-1/2);
5009 # for ($i=0; $i<$n; $i++)
5011 # for ($j=0; $j<$n; $j++)
5013 # if ( $j<=$i && $raw_values->[$i*($i+1)/2+$j]!=0 )
5015 # #print "Omega value = " . @other_val[$counter] . "\n";
5018 # #Only check the low-triangular off-diagonals of the omega matrix
5019 # #omega(i,j)>=sqrt(omega(i,i)*omega(j,j))
5020 # if ($j<=$i && $j!=$i &&
5021 # ($raw_values->[$i*($i+1)/2+$j]>=sqrt(
5022 # $raw_values->[$i*($i+1)/2+$i]*$raw_values->[$j*($j+1)/2+$j])))
5024 # print "Changing raw value at $i, $j: " . $raw_values->[$i*($i+1)/2+$j] ." to ".
5025 # (int(10000*sqrt($raw_values->[$i*($i+1)/2+$i]*$raw_values->[$j*($j+1)/2+$j]))/10000) ."\n";
5026 # #print "At index ($i,$j)\n" if ($self->{'debug'});
5027 # $raw_values->[$i*($i+1)/2+$j]=int(10000*sqrt(
5028 # $raw_values->[$i*($i+1)/2+$i]*$raw_values->[$j*($j+1)/2+$j]))/10000;
5029 # print "Changing omega value " . $values->[$counter-1] . " to " . $raw_values->[$i*($i+1)/2+$j] ."\n";
5030 # $values->[$counter-1] = $raw_values->[$i*($i+1)/2+$j];
5036 # #print "FL: ", Dumper @from_labels;
5037 # #print "OL: ", Dumper @own_labels;
5038 # print "FV: $param After ", Dumper(@from_values), "\n";
5044 for ( my $i = 0; $i <= $#own_labels; $i++ ) {
5046 if( $from_output -> have_user_defined_prior
){
5047 $ignore_missing_parameters = 1;
5049 unless ( $ignore_missing_parameters ) {
5050 my $from_name = defined $from_model ?
$from_model -> filename
:
5051 $from_output -> filename
;
5052 'debug' -> die( message
=> "Model -> update_inits: The number of ".$param.
5053 "s are not the same in from-model (" . $from_name .
5054 "): " . scalar @
{$from_labels[$i]} .
5055 ", and the model to be updated (" . $self -> {'filename'} .
5056 "): " . scalar @
{$own_labels[$i]} )
5057 unless ( scalar @
{$own_labels[$i]} ==
5058 scalar @
{$from_labels[$i]} );
5061 for ( my $j = 0; $j < scalar @
{$from_labels[$i]}; $j++ ) {
5062 for ( my $k = 0; $k < scalar @
{$own_labels[$i]}; $k++ ) {
5063 if ( $from_labels[$i][$j] eq $own_labels[$i][$k] ){
5064 $labels{$k+1} = $from_values[$i][0][$j];
5069 my @own_idxs = keys( %labels );
5071 for(my $i=0; $i <= $#own_idxs; $i++){
5072 @from_vals[$i] = $labels{ $own_idxs[$i] };
5075 $self -> initial_values
( problem_numbers
=> [$i+1],
5076 parameter_type
=> $param,
5077 parameter_numbers
=> [\
@own_idxs],
5078 new_values
=> [\
@from_vals] );
5090 # upper_bounds either sets or gets the initial values of the
5091 # parameter specified in I<parameter_type> for each
5092 # subproblem specified in I<problem_numbers>. For each
5093 # element in I<problem_numbers> there must be an array in
5094 # I<parameter_numbers> that specify the indices of the
5095 # parameters in the subproblem for which the upper bounds
5096 # are set, replaced or retrieved.
5098 @upper_bounds = @
{ $self -> _init_attr
5099 ( parameter_type
=> $parameter_type,
5100 parameter_numbers
=> \
@parameter_numbers,
5101 problem_numbers
=> \
@problem_numbers,
5102 new_values
=> \
@new_values,
5103 attribute
=> 'upbnd')};
5109 # {{{ clean_extra_data_code
5111 start clean_extra_data_code
5114 # This method cleans out old code for extra data. It searches
5115 # all subroutine statements in all problems for external
5116 # subroutines named "get_sub" and "reader" which are added by
5117 # "add_extra_data_code".
5119 foreach my $problem( @
{$self -> {'problems'}} ){
5120 if ( defined $problem -> subroutines
and defined $problem -> subroutines
-> [0] -> options
) {
5121 foreach my $option ( @
{$problem -> subroutines
-> [0] -> options
} ){
5122 if( lc($option -> name
) eq 'other'){
5123 if( lc($option -> value
) =~ /get_sub|reader/ ){
5125 # If we find "get_sub" or "reader" we remove
5126 # everything between "IMPORTING COVARIATE DATA" and
5127 # "IMPORTING COVARIATE DATA END" by finding the
5128 # indexes in the code array and and splicing it out.
5131 if( $problem -> pks
){
5132 # If the code is in a pk block:
5133 $code = $problem -> pks
-> [0] -> code
;
5135 $code = $problem -> preds
-> [0] -> code
;
5140 for( my $i = 0; $i <= $#{$code}; $i++ ){
5141 if( $code -> [$i] eq ";***IMPORTING COVARIATE DATA*******\n" ){
5144 if( $code -> [$i] eq ";***IMPORTING COVARIATE DATA END***\n" ){
5148 @
{$code} = ( @
{$code}[0..$start_idx] , @
{$code}[$end_idx..$#{$code}] );
5150 if( $problem -> pks
){
5151 # Put the cut down code back in the right place:
5152 $problem -> pks
-> [0] -> code
( $code );
5154 $problem -> preds
-> [0] -> code
( $code );
5164 end clean_extra_data_code
5166 # }}} clean_extra_data_code
5168 # {{{ add_extra_data_code
5170 start add_extra_data_code
5172 # This method adds fortran code that will handle wide datasets
5173 # (that is data sets with more than 20 columns). It adds code to
5174 # each problems pk or pred.
5178 # Get the headers of the columns that have been moved to another
5181 # unless( defined $self -> extra_data_headers ){
5182 # die "ERROR model::add_extra_data_code: No headers for the extra data file\n";
5185 # extra_data_headers is a two dimensional array. One array of
5186 # headers for each problem in the modelfile.
5187 for( my $i = 0; $i <= $#{$self -> {'problems'}}; $i++ ){
5188 if ( defined $self -> {'problems'} -> [$i] -> {'extra_data_header'} ) {
5189 my $problem_headers = $self -> {'problems'} -> [$i] -> {'extra_data_header'};
5194 # Loop over the problem specific headers and make a string
5195 # that will go into the fortran code. Assume that the
5196 # first column holds the ID, hence the $i=1
5197 for (my $i = 1; $i <= $#{$problem_headers}; $i++ ) {
5198 my $header = $problem_headers -> [$i];
5199 push( @headers, $header );
5200 # Chopp the string at 40 characters, to be nice to g77 :)
5201 if ( $length + length($header) > 40 ) {
5202 $header_string .= "\n\"& ";
5205 if ( $i < $#{$problem_headers} ) {
5206 $header_string .= 'I' . $header . ', ';
5207 $length += length( 'I' . $header . ', ' );
5209 $header_string .= 'I' . $header;
5210 $length += length( 'I' . $header );
5214 my @code_lines = ('',
5215 ';***IMPORTING COVARIATE DATA*******',
5217 '" REAL CURID, MID,',
5218 '"& '.$header_string,
5221 '" IF (.NOT.READ) THEN',
5227 '" IF (NEWIND.LT.2) THEN',
5228 '" CALL GET_SUB (NEWIND,ID,CURID,MID,',
5229 '"& '.$header_string. ')',
5232 ' IF (CID.NE.ID) THEN',
5233 ' PRINT *, \'ERROR CHECKING FAILED, CID = \', CID ,\' ID = \', ID',
5237 foreach my $header ( @headers ) {
5238 push( @code_lines, " $header = I$header" );
5241 push( @code_lines, (';***IMPORTING COVARIATE DATA END***','','') );
5243 my $problem = $self -> {'problems'} -> [$i];
5244 if ( defined $problem -> {'subroutines'} ) {
5245 $problem -> subroutines
-> [0] -> _add_option
( option_string
=> 'OTHER=get_sub'.$i.'.f' );
5246 $problem -> subroutines
-> [0] -> _add_option
( option_string
=> 'OTHER=reader'.$i.'.f');
5248 $problem -> add_records
( type
=> 'subroutine', record_strings
=> ['OTHER=get_sub'.$i.'.f', 'OTHER=reader'.$i.'.f'] );
5251 if ( defined $problem -> pks
) {
5252 unshift( @
{$problem -> pks
-> [0] -> code
}, join("\n", @code_lines ));
5254 unshift( @
{$problem -> preds
-> [0] -> code
},join("\n", @code_lines ));
5259 end add_extra_data_code
5267 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5268 $self -> {'datas'}[$i] -> drop_dropped
( model_header
=> $self -> {'problems'}[$i] -> header
);
5269 $self -> {'problems'}[$i] -> drop_dropped
( );
5270 #$self -> {'datas'}[$i] -> model_header( $self -> {'problems'}[$i] -> header );
5281 my $default_wrap = 18;
5283 $self -> drop_dropped
(1);
5285 my ( @wrap_columns, @cont_columns );
5286 if ( not defined $wrap_column ) {
5287 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5288 my $columns = scalar @
{$self -> {'problems'}[$i] -> dropped_columns
}-1; #skip ID
5289 my $modulus = $columns%($default_wrap-2); # default_wrap-2 to account for ID and CONT
5290 my $rows = (($columns-$modulus)/($default_wrap-2))+1;
5292 push( @wrap_columns, undef );
5294 push( @wrap_columns, (ceil
( $columns/$rows )+2) ); #Must use #cols + ID and CONT
5298 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5299 push( @wrap_columns, $wrap_column );
5303 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5304 next if ( not defined $wrap_columns[$i] );
5305 $wrap_column = $wrap_columns[$i];
5306 $cont_column = $wrap_columns[$i] if( not defined $cont_column );
5307 my ( $prim, $sec ) =
5308 $self -> {'datas'}[$i] -> wrap
( cont_column
=> $cont_column,
5309 wrap_column
=> $wrap_column,
5310 model_header
=> $self -> {'problems'}[$i] -> header
);
5311 $self -> {'problems'}[$i] -> primary_columns
( $prim );
5312 $self -> {'problems'}[$i] -> secondary_columns
( $sec );
5313 $self -> {'data_wrapped'}++;
5323 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5324 $self -> {'datas'}[$i] -> unwrap
;
5325 $self -> {'problems'}[$i] -> primary_columns
( [] );
5326 $self -> {'problems'}[$i] -> secondary_columns
( [] );
5328 $self -> {'data_wrapped'} = 0;
5333 # {{{ write_get_subs
5335 start write_get_subs
5337 for( my $i = 0; $i <= $#{$self -> {'problems'}}; $i++ ){
5338 if ( defined $self -> {'problems'} -> [$i] -> {'extra_data_header'} and
5339 defined $self -> problems
-> [$i] -> extra_data
) {
5340 my @problem_header = @
{$self -> {'problems'} -> [$i] -> {'extra_data_header'}};
5345 my $rows = $self -> problems
-> [$i] -> extra_data
-> count_ind
;
5347 # Assume that first column holds the ID. Get rid of it.
5348 shift( @problem_header );
5349 for ( my $i = 0; $i <= $#problem_header; $i++ ) {
5350 my $header = $problem_header[$i];
5351 push( @headers, $header );
5352 # Chop the string at 40 characters, to be nice to g77 :)
5353 if ( $length + length($header) > 40 ) {
5354 $header_string .= "\n & ";
5357 if ( $i < $#problem_header ) {
5358 $header_string .= $header . ', ';
5359 $length += length( $header . ', ' );
5361 $header_string .= $header;
5362 $length += length( $header );
5366 open( FILE
, '>', 'get_sub' . $i . '.f' );
5367 print FILE
(" SUBROUTINE GET_SUB (NEWIND,ID,CURID,MID,\n",
5368 " & $header_string)\n",
5369 " COMMON /READ/ TID,TCOV\n",
5371 " REAL ID,CURID,MID,\n",
5372 " & $header_string\n",
5374 " INTEGER NEWIND\n",
5376 " REAL TID($rows), TCOV($rows,",scalar @problem_header,")\n",
5379 "C START AT TOP EVERY TIME\n",
5380 " IF (NEWIND.EQ.1) THEN \n",
5382 " IF (CURID.GT.$rows) THEN \n",
5383 " PRINT *, \"Covariate data not found for\", ID\n",
5388 " IF (ID.GT.TID (CURID)) THEN\n",
5389 " CURID = CURID + 1\n",
5392 " ELSEIF (NEWIND.EQ.0) THEN\n",
5397 for ( my $i = 1; $i <= $#headers+1; $i++ ) {
5398 $length += length("TCOV(I,$i),");
5399 if ( $length > 40 ) {
5403 print FILE
" ".$headers[$i-1] . " = TCOV(CURID,$i)\n";
5406 print FILE
(" MID = TID(CURID)\n",
5423 for( my $i = 0; $i <= $#{$self -> {'problems'}}; $i++ ){
5424 if ( defined $self -> {'problems'} -> [$i] -> {'extra_data_header'} and
5425 defined $self -> {'problems'} -> [$i] -> {'extra_data'} ) {
5426 my @problem_header = @
{$self -> {'problems'} -> [$i] -> {'extra_data_header'}};
5430 my $rows = $self -> problems
-> [$i] -> extra_data
-> count_ind
;
5431 my $filename = $self -> problems
-> [$i] -> extra_data
-> filename
;
5432 # Assume that first column holds the ID. Get rid of it.
5433 shift( @problem_header );
5435 'debug' -> warn( level
=> 2,
5436 message
=> "Writing reader".$i.".f to directory".cwd
);
5437 open( FILE
, '>', 'reader' . $i . '.f' );
5438 print FILE
(" SUBROUTINE READER()\n",
5440 " COMMON /READ/ TID,TCOV\n",
5442 " REAL TID ($rows), TCOV ($rows, ",scalar @problem_header,")\n",
5444 " OPEN (UNIT = 77,FILE = '$filename')\n",
5446 " DO 11,I = 1,$rows\n",
5447 " READ (77,*) TID(I)," );
5450 for ( my $i = 1; $i <= $#problem_header+1; $i++ ) {
5451 $length += length("TCOV(I,$i),");
5452 if ( $length > 40 ) {
5456 if ( $i <= $#problem_header ) {
5457 print FILE
"TCOV(I,$i),";
5459 print FILE
"TCOV(I,$i)\n";
5463 print FILE
( "11 CONTINUE\n",
5477 # $model -> _write( filename => 'model.mod' );
5479 # Writes the content of the modelobject to disk. Either to the
5480 # filename given, or to the string returned by model::full_name.
5484 # An element in the active_problems array is a boolean that
5485 # corresponds to the element with the same index in the problems
5486 # array. If the boolean is true, the problem will be run. All
5487 # other will be commented out.
5488 my @active = @
{$self -> {'active_problems'}};
5490 # loop over all problems.
5491 for ( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5492 # Call on the problem object to format it as text. The
5493 # filename and problem numbers are needed to make some
5494 # autogenerated files (msfi, tabels etc...) unique to the
5496 my @preformatted = @
{$self -> {'problems'} -> [$i] ->
5497 _format_problem
( filename
=> $self -> filename
,
5498 problem_number
=> ($i+1) ) };
5499 # Check if the problem is NOT active, if so comment it out.
5500 unless ( $active[$i] ) {
5501 for ( my $j = 0; $j <= $#preformatted; $j++ ) {
5502 $preformatted[$j] = '; '.$preformatted[$j];
5505 # Add extra line to avoid problems with execution of NONMEM
5506 push(@preformatted,"\n");
5507 push( @formatted, @preformatted );
5510 # Open a file and print the formatted problems.
5511 # TODO Add some errorchecking.
5512 open( FILE
, '>'. $filename );
5513 for ( @formatted ) {
5520 if ( $write_data ) {
5521 foreach my $data ( @
{$self -> {'datas'}} ) {
5526 if( $self -> {'iofv_modules'} ){
5527 $self -> {'iofv_modules'} -> [0] -> post_process
;
5538 if ( defined $parm and $parm ne $self -> {'filename'} ) {
5539 $self -> {'filename'} = $parm;
5540 $self -> {'model_id'} = undef;
5547 # {{{ _get_option_val_pos
5549 start _get_option_val_pos
5553 # ( $values_ref, $positions_ref ) ->
5554 # _get_option_val_pos ( name => 'ID',
5555 # record_name => 'input' );
5556 # my @values = @{$values_ref};
5557 # my @positions = @{$positions_ref};
5559 # This basic usage returns the name of the third option in the first
5560 # instance of the record specified by I<record_name> for all problems
5562 # If global_position is set to 1, only one value and position
5563 # pair is returned per problem. If there are more than one
5564 # match in the model; the first will be returned for each
5567 # Private method, should preferably not be used outside model.pm
5569 # my ( @records, @instances );
5570 my $accessor = $record_name.'s';
5571 my @problems = @
{$self -> {'problems'}};
5572 unless( $#problem_numbers > 0 ){
5573 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5575 foreach my $i ( @problem_numbers ) {
5576 my $rec_ref = $problems[ $i-1 ] -> $accessor;
5577 if ( defined $problems[ $i-1 ] and defined $rec_ref ) {
5578 my @records = @
{$rec_ref};
5579 unless( $#instances > 0 ){
5580 @instances = (1 .. $#records+1);
5583 my @inst_values = ();
5584 my @inst_positions = ();
5586 my ( $glob_value, $glob_position );
5587 INSTANCES
: foreach my $j ( @instances ) {
5588 if ( defined $records[ $j-1 ] ) {
5590 my ( $value, $position );
5591 foreach my $option ( @
{$records[$j-1] -> {'options'}} ) {
5592 if ( defined $option and $option -> name
eq $name) {
5593 if ( $global_position ) {
5594 $glob_value = $option -> value
;
5595 $glob_position = $glob_pos;
5598 $value = $option -> value
;
5605 push( @inst_values, $value );
5606 push( @inst_positions, $position );
5608 'debug' -> die( message
=> "Instance $j in problem number $i does not exist!" )
5611 if ( $global_position ) {
5612 push( @values, $glob_value );
5613 push( @positions, $glob_position );
5615 push( @values, \
@inst_values );
5616 push( @positions, \
@inst_positions );
5619 'debug' -> die( message
=> "Problem number $i does not exist!" );
5622 # if( defined $problem_number ) {
5623 # if( $problem_number < 1 or $problem_number > scalar @problems ) {
5624 # die "model -> _get_option_val_pos: No such problem number, ",
5625 # $problem_number,", in this model!\n";
5629 # die "modelfile -> _get_option_val_pos: No problem $problem_number exists\n"
5630 # if( (scalar @problems < 1) and ($problem_number ne 'all') );
5632 # foreach my $problem ( @problems ) {
5633 # @records = @{$problem -> $accessor};
5634 # @records = ($records[$instance-1]) if ( $instance ne 'all' );
5635 # die "modelfile -> _get_option_val_pos: No record instance $instance ".
5636 # "of record $record_name in problem $problem_number exists\n"
5637 # if( (scalar @records < 1) and ($instance ne 'all') );
5638 # foreach my $record ( @records ) {
5640 # foreach my $option ( @{$record -> {'options'}} ) {
5641 # if ( defined $option and $option -> name eq $name) {
5642 # print "Found $name at $i\n" if ( $self -> {'debug'} );
5643 # push( @values, $option -> value );
5644 # push( @positions, $i );
5651 end _get_option_val_pos
5653 # }}} _get_option_val_pos
5659 # The I<add_if_absent> argument tells the method to add an init (theta,omega,sigma)
5660 # if the parameter number points to a non-existing parameter with parameter number
5661 # one higher than the highest presently included. Only applicatble if
5662 # I<new_values> are set. Default value = 0;
5664 unless( scalar @problem_numbers > 0 ){
5665 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5667 my @problems = @
{$self -> {'problems'}};
5668 if ( $#new_values >= 0 ) {
5669 'debug' -> die( message
=> "The number of new value sets " .
5670 ($#new_values+1) . " do not" .
5671 " match the number of problems " . ($#problem_numbers+1) . " specified" )
5672 unless(($#new_values == $#problem_numbers) );
5673 if ( $#parameter_numbers > 0 ) {
5674 'debug' -> die( message
=> "The number of parameter number sets do not" .
5675 " match the number of problems specified" )
5676 unless(($#parameter_numbers == $#problem_numbers) );
5680 my $new_val_idx = 0;
5681 foreach my $i ( @problem_numbers ) {
5682 if ( defined $problems[ $i-1 ] ) {
5683 if ( scalar @new_values > 0) {
5685 # Use attribute parameter_values to collect diagnostic outputs
5686 push( @parameter_values,
5687 $problems[ $i-1 ] ->
5688 _init_attr
( parameter_type
=> $parameter_type,
5689 parameter_numbers
=> $parameter_numbers[ $new_val_idx ],
5690 new_values
=> \@
{$new_values[ $new_val_idx ]},
5691 attribute
=> $attribute,
5692 add_if_absent
=> $add_if_absent ) );
5695 # {{{ Retrieve values
5696 push( @parameter_values,
5697 $problems[ $i-1 ] ->
5698 _init_attr
( parameter_type
=> $parameter_type,
5699 parameter_numbers
=> $parameter_numbers[ $i-1 ],
5700 attribute
=> $attribute ) );
5701 # }}} Retrieve values
5704 'debug' -> die( message
=> "Problem number $i does not exist!" );
5719 # $modobj -> _option_name ( record => $record_name,
5722 # This basic usage returns the name of the third option in the first
5723 # instance of the record specified by I<record>.
5726 my ( @problems, @records, @options, $i );
5727 my $accessor = $record.'s';
5728 if ( defined $self -> {'problems'} ) {
5729 @problems = @
{$self -> {'problems'}};
5731 'debug' -> die( message
=> "No problems defined in model" );
5733 if ( defined $problems[$problem_number - 1] -> $accessor ) {
5734 @records = @
{$problems[$problem_number - 1] -> $accessor};
5736 'debug' -> die( message
=> "No record $record defined in ".
5737 "problem number $problem_number." );
5739 if ( defined $records[$instance - 1] -> options
) {
5740 @options = @
{$records[$instance - 1] -> options
};
5742 'debug' -> die( message
=> "model -> _option_name: No option defined in record ".
5743 "$record in problem number $problem_number." );
5746 foreach my $option ( @options ) {
5747 if ( $i == $position ) {
5748 if ( defined $new_name ){
5749 $option -> name
($new_name) if ( defined $option );
5751 $name = $option -> name
if ( defined $option );
5761 # {{{ _parameter_count
5762 start _parameter_count
5764 if( defined $self -> {'problems'} ){
5765 my $problems = $self -> {'problems'};
5766 if( defined @
{$problems}[$problem_number - 1] ){
5767 $count = @
{$problems}[$problem_number - 1] -> record_count
( 'record_name' => $record );
5771 end _parameter_count
5772 # }}} _parameter_count
5774 # {{{ _read_problems
5776 start _read_problems
5779 # To read problems from a modelfile we need its full name
5780 # (meaning filename and path). And we need an array for the
5781 # modelfile lines and an array with indexes telling where
5782 # problems start in the modelfile array.
5785 my $file = $self -> full_name
;
5786 my ( @modelfile, @problems );
5787 my ( @problem_start_index );
5789 # Check if the file is missing, and if that is ok.
5790 # TODO Check accessor what happens if the file is missing.
5792 return if( not (-e
$file) && $self -> {'ignore_missing_files'} );
5794 # Open the file, slurp it and close it
5795 open( FILE
, "$file" ) ||
5796 'debug' -> die( message
=> "Model -> _read_problems: Could not open $file".
5798 @modelfile = <FILE
>;
5801 my @extra_data_files = defined $self ->{'extra_data_files'} ?
5802 @
{$self -> {'extra_data_files'}} : ();
5803 my @extra_data_headers = defined $self ->{'extra_data_headers'} ?
5804 @
{$self -> {'extra_data_headers'}} : ();
5807 # # Find the indexes where the problems start
5808 # for ( my $i = 0; $i <= $#modelfile; $i++ ) {
5809 # push( @problem_start_index, $i )if ( $modelfile[$i] =~ /\$PROB/ );
5812 # # Loop over the number of problems. Copy the each problems lines
5813 # # and create a problem object.
5815 # for( my $i = 0; $i <= $#problem_start_index; $i++ ) {
5816 # my $start_index = $problem_start_index[$i];
5817 # my $end_index = defined $problem_start_index[$i+1] ? $problem_start_index[$i+1] - 1: $#modelfile ;
5819 # my @problem_lines = @modelfile[$start_index .. $end_index];
5821 # # Problem object creation.
5822 # push( @problems, model::problem -> new ( debug => $self -> {'debug'},
5823 # ignore_missing_files => $self -> {'ignore_missing_files'},
5824 # prob_arr => \@problem_lines,
5825 # extra_data_file_name => $extra_data_files[$i],
5826 # extra_data_header => $extra_data_headers[$i]) );
5828 my $start_index = 0;
5833 # It may look like the loop takes one step to much, but its a
5834 # trick that helps parsing the last problem.
5835 for ( my $i = 0; $i <= @modelfile; $i++ ) {
5836 if( $i <= $#modelfile ){
5837 $_ = $modelfile[$i];
5840 if ($first and not /^\s*(;|\$PROB|$)/){
5841 'debug' -> die( message
=> 'Model -> _read_problems: '.
5842 "First non-comment line in modelfile $file \n".
5843 'is not a $PROB record. NONMEM syntax violation.');
5846 # In this if statement we use the lazy evaluation of logical
5847 # or to make sure we only execute search pattern when we have
5848 # a line to search. Which is all cases but the very last loop
5851 if( $i > $#modelfile or /^\s*\$PROB/ ){
5854 # The if statement here is only necessary in the first loop
5855 # iteration. When start_index == end_index == 0 we want to
5856 # skip to the next iteration looking for the actual end of
5857 # the first problem.
5859 if( $end_index > $start_index and not $first ){
5860 # extract lines of code:
5861 my @problem_lines = @modelfile[$start_index .. $end_index-1];
5862 # reset the search for problems by moving the problem start
5866 my $sh_mod = model
::shrinkage_module
-> new
( model
=> $self,
5867 temp_problem_number
=> ($#problems+2));
5868 my $prob = model
::problem
->
5869 new
( directory
=> $self -> {'directory'},
5870 ignore_missing_files
=> $self -> {'ignore_missing_files'},
5871 ignore_missing_output_files
=> $self -> {'ignore_missing_output_files'},
5872 sde
=> $self -> {'sde'},
5873 cwres
=> $self -> {'cwres'},
5874 mirror_plots
=> $self -> {'mirror_plots'},
5875 nm_version
=> $self -> {'nm_version'},
5876 prob_arr
=> \
@problem_lines,
5877 extra_data_file_name
=> $extra_data_files[$prob_num],
5878 extra_data_header
=> $extra_data_headers[$prob_num],
5879 shrinkage_module
=> $sh_mod );
5880 push( @problems, $prob );
5881 if ( $self -> cwres
() ) {
5883 if ( defined $self -> extra_output
() ) {
5884 @eo = @
{$self -> extra_output
()};
5886 if( $prob -> {'cwres_modules'} ){
5887 push( @eo, @
{$prob -> {'cwres_modules'} -> [0] -> cwtab_names
()} );
5889 $self -> extra_output
( \
@eo );
5892 $sh_mod -> problem
( $problems[$#problems] );
5899 # Set the problems in the modelobject.
5900 if (scalar(@problems)<1){
5901 'debug' -> die( message
=> 'Model -> _read_problems: '.
5902 "Could not find any problem in modelfile $file");
5904 $self -> problems
(\
@problems);
5908 # }}} _read_problems
5914 unless( $#problem_numbers >= 0 ){
5915 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5918 my @problems = @
{$self -> {'problems'}};
5919 foreach my $i ( @problem_numbers ) {
5920 if ( defined $problems[ $i-1 ] ) {
5921 my $found = $self -> is_option_set
( 'problem_number' => $i,
5922 'record' => $record_name,
5923 'name' => $option_name,
5924 'fuzzy_match' => $fuzzy_match );
5925 $problems[$i-1] -> remove_option
( record_name
=> $record_name,
5926 option_name
=> $option_name,
5927 fuzzy_match
=> $fuzzy_match ) if ( $found );
5928 $problems[$i-1] -> add_option
( record_name
=> $record_name,
5929 option_name
=> $option_name,
5930 option_value
=> $option_value );
5942 unless( $#problem_numbers >= 0 ){
5943 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5946 my @problems = @
{$self -> {'problems'}};
5947 foreach my $i ( @problem_numbers ) {
5948 if ( defined $problems[ $i-1 ] ) {
5949 $problems[$i-1] -> add_option
( record_name
=> $record_name,
5950 option_name
=> $option_name,
5951 option_value
=> $option_value,
5952 add_record
=> $add_record );
5964 unless( $#problem_numbers >= 0 ){
5965 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5968 my @problems = @
{$self -> {'problems'}};
5969 foreach my $i ( @problem_numbers ) {
5970 if ( defined $problems[ $i-1 ] ) {
5971 $problems[$i-1] -> remove_option
( record_name
=> $record_name,
5972 option_name
=> $option_name,
5973 fuzzy_match
=> $fuzzy_match);
5981 # {{{ _option_val_pos
5983 start _option_val_pos
5985 unless( $#problem_numbers >= 0 ){
5986 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5988 my @problems = @
{$self -> {'problems'}};
5989 if ( $#new_values >= 0 ) {
5990 'debug' -> die( message
=> "Trying to set option $name in record $record_name but the ".
5991 "number of new value sets (".
5993 "), do not match the number of problems specified (".
5994 ($#problem_numbers+1).")" )
5995 unless(($#new_values == $#problem_numbers) );
5996 if ( $#instance_numbers > 0 ) {
5997 'debug' -> die( message
=> "The number of instance number sets (".
5998 ($#instance_numbers+1).
5999 "),do not match the number of problems specified (".
6000 ($#problem_numbers+1).")" )
6001 unless(($#instance_numbers == $#problem_numbers) );
6005 foreach my $i ( @problem_numbers ) {
6006 if ( defined $problems[ $i-1 ] ) {
6007 my $rn_ref = $#instance_numbers >= 0 ? \@
{$instance_numbers[ $i-1 ]} : [];
6008 if ( scalar @new_values > 0) {
6011 if( not defined $new_values[ $i-1 ] ) {
6012 debug
-> die( message
=> " The specified new_values was undefined for problem $i" );
6015 if( not ref( $new_values[ $i-1 ] ) eq 'ARRAY' ) {
6016 debug
-> die( message
=> " The specified new_values for problem $i is not an array as it should be but a ".
6017 ( defined ref( $new_values[ $i-1 ] ) ?
6018 ref( $new_values[ $i-1 ] ) : 'undef' ) );
6021 $problems[ $i-1 ] ->
6022 _option_val_pos
( record_name
=> $record_name,
6023 instance_numbers
=> $rn_ref,
6024 new_values
=> \@
{$new_values[ $i-1 ]},
6026 exact_match
=> $exact_match );
6030 # {{{ Retrieve values
6031 my ( $val_ref, $pos_ref ) =
6032 $problems[ $i-1 ] ->
6033 _option_val_pos
( record_name
=> $record_name,
6034 instance_numbers
=> $rn_ref,
6036 exact_match
=> $exact_match );
6037 push( @values, $val_ref );
6038 push( @positions, $pos_ref );
6039 # }}} Retrieve values
6042 'debug' -> die( message
=> "Problem number $i does not exist!" );
6048 # }}} _option_val_pos
6050 # {{{ subroutine_files
6052 start subroutine_files
6055 foreach my $subr( 'PRED','CRIT', 'CONTR', 'CCONTR', 'MIX', 'CONPAR', 'OTHER', 'PRIOR' ){
6056 my ( $model_fsubs, $junk ) = $self -> _option_val_pos
( record_name
=> 'subroutine',
6058 if( @
{$model_fsubs} > 0 ){
6059 foreach my $prob_fsubs ( @
{$model_fsubs} ){
6060 foreach my $fsub( @
{$prob_fsubs} ){
6067 # BUG , nonmem6 might not require the file to be named .f And I've
6068 # seen examples of files named .txt
6070 @fsubs = keys %fsubs;
6072 for( my $i = 0; $i <= $#fsubs; $i ++ ){
6073 unless( $fsubs[$i] =~ /\.f$/ ){
6079 end subroutine_files
6083 # {{{ get_option_value
6084 start get_option_value
6086 #$modelObject -> get_option_value(record_name => 'recordName', option_name => 'optionName',
6087 # problem_index => <index>, record_index => <index>/'all',
6088 # option_index => <index>/'all')
6089 # record_name and option_name are required. All other have default 0.
6090 #record_index and option_index may either be scalar integer or string 'all'.
6091 # Depending on input parameters the return value can be
6092 # Case 1. a scalar for record_index => integer, option_index => integer
6093 # Case 2. a reference to an array of scalars for (record_index=>'all',option_index => integer)
6094 # Case 3. a reference to an array of scalars for (record_index=>integer,option_index => 'all')
6095 # Case 4. a reference to an array of references to arrays for (record_index=>'all',option_index => 'all')
6096 my ( @problems, @records, @options );
6097 my $accessor = $record_name.'s';
6101 # print "start get option\n";
6103 #Basic error checking. Error return type is undef for Case 1
6104 #and reference to empty array for Case 2 and 3 and 4.
6106 if (lc($record_index) eq 'all' || lc($option_index) eq 'all' ){
6112 if ( defined $self -> {'problems'} ) {
6113 @problems = @
{$self -> {'problems'}};
6115 'debug' -> warn( level
=> 2,message
=> "No problems defined in model" );
6118 unless( defined $problems[$problem_index] ){
6119 'debug' -> warn( level
=> 2,
6120 message
=> "model -> get_option_value: No problem with ".
6121 "index $problem_index defined in model" );
6125 if ( defined $problems[$problem_index] -> $accessor ) {
6126 @records = @
{$problems[$problem_index] -> $accessor};
6128 'debug' -> warn( level
=> 2,
6129 message
=> "model -> get_option_value: No record $record_name defined" .
6130 " in problem with index $problem_index." );
6134 #go through all records, whole array is of correct type.
6135 #if current record is the single we want, investigare option values and break out of loop
6136 #if we want to look at all records, investigare option values and continue with loop
6137 REC
: for (my $ri=0; $ri<scalar(@records); $ri++){
6138 if ((lc($record_index) eq 'all') || $record_index==$ri){
6140 unless ((defined $records[$ri]) &&( defined $records[$ri] -> options
)){
6141 'debug' -> warn( level
=> 2,
6142 message
=> "model -> get_option_value: No options for record index ".
6143 "$record_index defined in problem." );
6144 if (lc($record_index) eq 'all'){
6145 if (lc($option_index) eq 'all'){
6146 push(@rec_arr,[]); #Case 4
6148 push(@rec_arr,undef); #Case 2
6152 if (lc($option_index) eq 'all'){
6153 $return_value = []; #Case 3
6155 $return_value = undef; #Case 1
6157 last REC
; #we are done
6160 @options = @
{$records[$ri] -> options
};
6163 #go through all options (array contains all options, regardless of name).
6164 # For each check if it the correct type, if so
6165 #increase counter $oi after possibly storing the option value
6166 #if current correct option is the single we want value for, then
6167 #store value and break out of loop. If want to store values for
6168 #all correct options, store value and then continue with loop
6169 foreach my $option ( @options ) {
6170 if (defined $option and
6171 (($option->name eq $option_name) || (index($option_name,$option ->name ) > -1))){
6173 if (lc($option_index) eq 'all' || $option_index == $oi){
6174 if ( (defined $option -> {'value'}) and ($option -> {'value'} ne '')){
6175 $val = $option -> {'value'};
6179 if (lc($option_index) eq 'all'){
6180 push(@val_arr,$val); #Case 3 and 4
6182 last; #Case 1 and 2. Take care of $val outside loop over options
6187 if (lc($record_index) eq 'all'){
6188 if (lc($option_index) eq 'all'){
6189 push(@rec_arr,\
@val_arr); #Case 4
6191 push(@rec_arr,$val); #Case 2
6195 if (lc($option_index) eq 'all'){
6196 $return_value = \
@val_arr; #Case 3
6198 $return_value = $val; #Case 1
6204 if (lc($record_index) eq 'all'){
6205 $return_value = \
@rec_arr; #Case 2 and 4
6209 end get_option_value
6211 # }}} get_option_value