1 # TODO: All: 2004-09-06 Fix absolute paths for data and output files. (under both
6 start include statements
7 use Digest
::MD5
'md5_hex';
14 use POSIX
qw(ceil floor);
15 use model
::shrinkage_module
;
16 end include statements
18 # }}} include statements
20 # {{{ description, synopsis and see_also
22 # No method, just documentation
27 PsN::model is a Perl module for parsing and manipulating NONMEM model
30 The model class is built around the NONMEM model file. This is an
31 ordinary ASCII text file that, except for the data, holds all
32 information needed for fitting a non-linear mixed effect model using
33 NONMEM. Typically, a model file contains specifications for a
34 pharmacokinetic and/or a pharmacodynamic model, initial estimates of
35 model parameters, boundaries for model parameters as well as details
36 about the data location and format.
48 C<< my $model_object = model -> new ( filename => 'pheno.mod' ); >>
56 $model_object -> initial_values ( parameter_type => 'theta',
57 parameter_numbers => [[1,3]],
58 new_values => [[1.2,34]] );
76 <a HREF="data.html">data</a>, <a HREF="output.html">output</a>
104 $model = model -> new( filename => 'run1.mod' )
108 This is the simplest and most common way to create a model
109 object and it requires a file on disk.
113 $model = model -> new( filename => 'run1.mod',
118 If the target parameter is set to anything other than I<mem>
119 the output object (with file name given by the model
120 attribute I<outputfile>) and the data objects (identified by
121 the data file names in the $DATA NONMEM model file section)
122 will be initialized but will contain no information from
123 their files. If information from them are requiered later
124 on, they are read and parsed and the appropriate attributes
125 of the data and output objects are set.
132 if ( defined $parm{'problems'} ) {
133 $this -> {'problems'} = $parm{'problems'};
135 ($this -> {'directory'}, $this -> {'filename'}) =
136 OSspecific
::absolute_path
( $this -> {'directory'}, $this -> {'filename'} );
137 $this -> _read_problems
;
138 $this -> {'synced'} = 1;
141 if ( defined $parm{'active_problems'} ) {
142 $this -> {'active_problems'} = $parm{'active_problems'};
143 } elsif ( defined $this -> {'problems'} ) {
145 for ( @
{$this -> {'problems'}} ) {
148 $this -> {'active_problems'} = \
@active;
151 if ( defined $this -> {'extra_data_files'} ){
152 for( my $i; $i < scalar @
{$this -> {'extra_data_files'}}; $i++ ){
153 my ( $dir, $file ) = OSspecific
::absolute_path
( $this -> {'directory'}, $this -> {'extra_data_files'} -> [$i]);
154 $this -> {'extra_data_files'} -> [$i] = $dir . $file;
158 my $subroutine_files = $this -> subroutine_files
;
159 if( defined $subroutine_files and scalar @
{$subroutine_files} > 0 ){
160 push( @
{$this -> {'extra_files'}}, @
{$subroutine_files} );
163 if ( defined $this -> {'extra_files'} ){
164 for( my $i; $i < scalar @
{$this -> {'extra_files'}}; $i++ ){
165 my ( $dir, $file ) = OSspecific
::absolute_path
( $this -> {'directory'}, $this -> {'extra_files'} -> [$i]);
166 $this -> {'extra_files'} -> [$i] = $dir . $file;
170 # Read datafiles, if any.
171 unless( defined $this -> {'datas'} and not $this -> {'quick_reload'} ){
172 my @idcolumns = @
{$this -> idcolumns
};
173 my @datafiles = @
{$this -> datafiles
('absolute_path' => 1)};
174 # my @datafiles = @{$this -> datafiles('absolute_path' => 0)};
175 for ( my $i = 0; $i <= $#datafiles; $i++ ) {
176 my $datafile = $datafiles[$i];
177 my $idcolumn = $idcolumns[$i];
178 my ( $cont_column, $wrap_column ) = $this -> {'problems'} -> [$i] -> cont_wrap_columns
;
179 my $ignoresign = defined $this -> ignoresigns ?
$this -> ignoresigns
-> [$i] : undef;
180 my @model_header = @
{$this -> {'problems'} -> [$i] -> header
};
181 if ( defined $idcolumn ) {
182 push ( @
{$this -> {'datas'}}, data
->
183 new
( idcolumn
=> $idcolumn,
184 filename
=> $datafile,
185 cont_column
=> $cont_column,
186 wrap_column
=> $wrap_column,
187 #model_header => \@model_header,
188 ignoresign
=> $ignoresign,
189 directory
=> $this -> {'directory'},
190 ignore_missing_files
=> $this -> {'ignore_missing_files'} ||
191 $this -> {'ignore_missing_data'},
192 target
=> $this -> {'target'}) );
194 'debug' -> die( message
=> "New model to be created from ".$this -> full_name
().
195 ". Data file is ".$datafile.
196 ". No id column definition found in the model file." );
201 # Read outputfile, if any.
202 if( ! defined $this -> {'outputs'} ) {
203 unless( defined $this -> {'outputfile'} ){
204 if( $this -> filename
() =~ /\.mod$/ ) {
205 ($this -> {'outputfile'} = $this -> {'filename'}) =~ s/\.mod$/.lst/;
207 $this -> outputfile
( $this -> filename
().'.lst' );
210 push ( @
{$this -> {'outputs'}}, output
->
211 new
( filename
=> $this -> {'outputfile'},
212 directory
=> $this -> {'directory'},
213 ignore_missing_files
=>
214 $this -> {'ignore_missing_files'} || $this -> {'ignore_missing_output_files'},
215 target
=> $this -> {'target'},
216 model_id
=> $this -> {'model_id'} ) );
219 # Adding mirror_plots module here, since it can add
220 # $PROBLEMS. Also it needs to know wheter an lst file exists
223 if( $this -> {'mirror_plots'} > 0 ){
224 my $mirror_plot_module = model
::mirror_plot_module
-> new
( base_model
=> $this,
225 nr_of_mirrors
=> $this -> {'mirror_plots'},
226 cwres
=> $this -> {'cwres'},
227 mirror_from_lst
=> $this -> {'mirror_from_lst'});
228 push( @
{$this -> {'mirror_plot_modules'}}, $mirror_plot_module );
231 if( $this -> {'iofv'} > 0 ){
232 my $iofv_module = model
::iofv_module
-> new
( base_model
=> $this,
233 nm_version
=> $this -> {'nm_version'});
234 push( @
{$this -> {'iofv_modules'}}, $iofv_module );
242 # {{{ register_in_database
244 start register_in_database
246 if ( $PsN::config
-> {'_'} -> {'use_database'} ) {
247 # Backslashes messes up the sql syntax
248 my $file_str = $self->{'filename'};
249 my $dir_str = $self->{'directory'};
250 $file_str =~ s/\\/\//g
;
251 $dir_str =~ s/\\/\//g
;
254 my $md5sum = md5_hex
(OSspecific
::slurp_file
($self-> full_name
));
256 my $dbh = DBI
-> connect("DBI:mysql:host=".$PsN::config
-> {'_'} -> {'database_server'}.
257 ";databse=".$PsN::config
-> {'_'} -> {'project'},
258 $PsN::config
-> {'_'} -> {'user'},
259 $PsN::config
-> {'_'} -> {'password'},
260 {'RaiseError' => 1});
267 my $sth = $dbh -> prepare
( "SELECT model_id FROM ".$PsN::config
-> {'_'} -> {'project'}.
269 "WHERE filename = '$file_str' AND ".
270 "directory = '$dir_str' AND ".
271 "md5sum = '".$md5sum."'" );
272 $sth -> execute
or 'debug' -> die( message
=> $sth->errstr ) ;
274 $select_arr = $sth -> fetchall_arrayref
;
277 if ( scalar @
{$select_arr} > 0 ) {
278 'debug' -> warn( level
=> 1,
279 message
=> "Found an old entry in the database matching the ".
280 "current model file" );
281 if ( scalar @
{$select_arr} > 1 ) {
282 'debug' -> warn( level
=> 1,
283 message
=> "Found more than one matching entry in database".
284 ", using the first" );
286 $self -> {'model_id'} = $select_arr->[0][0];
288 my ( $date_str, $time_str );
289 if( $Config{osname
} eq 'MSWin32' ){
290 $date_str = `date /T`;
291 $time_str = ' '.`time /T`;
298 my $date_time = $date_str.$time_str;
299 $sth = $dbh -> prepare
("INSERT INTO ".$PsN::config
-> {'_'} -> {'project'}.
300 ".model (filename,date,directory,md5sum) ".
301 "VALUES ('$file_str', '$date_time', '$dir_str','".
304 $self -> {'model_id'} = $sth->{'mysql_insertid'};
306 $sth -> finish
if ( defined $sth );
309 $model_id = $self -> {'model_id'} # return the model_id;
311 end register_in_database
313 # }}} register_in_database
315 # {{{ shrinkage_stats
317 start shrinkage_stats
319 if ( $#problem_numbers > 0 and ref $enabled eq 'ARRAY' ){
320 if ( $#problem_numbers != ( scalar @
{$enabled} - 1 ) ) {
321 'debug' -> die( message
=> "The number of problem_numbers ".($#problem_numbers+1).
322 "and enabled/disabled shrinkage_stats ".scalar @
{$enabled}.
326 unless( $#problem_numbers > 0 ){
327 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
330 if( ref \
$enabled eq 'SCALAR' ) {
331 for ( @problem_numbers ) {
332 push( @en_arr, $enabled );
334 } elsif ( not ref $enabled eq 'ARRAY' ) {
335 debug
-> die( message
=> 'enabled must be a scalar or a reference to an array, '.
336 'not a reference to a '.ref($enabled).'.' );
339 my @problems = @
{$self -> {'problems'}};
341 foreach my $i ( @problem_numbers ) {
342 if ( defined $problems[ $i-1 ] ) {
343 if ( defined $en_arr[ $j ] ) {
344 if( $en_arr[ $j ] ) {
345 $problems[ $i-1 ] -> shrinkage_module
-> enable
;
347 $problems[ $i-1 ] -> shrinkage_module
-> disable
;
349 # my $eta_file = $self -> filename.'_'.$i.'.etas';
350 # my $eps_file = $self -> filename.'_'.$i.'.wres';
351 # $problems[ $i-1 ] -> {'eta_shrinkage_table'} = $eta_file;
352 # $problems[ $i-1 ] -> {'wres_shrinkage_table'} = $eps_file;
354 push( @indicators, $problems[ $i-1 ] -> shrinkage_module
-> status
);
357 'debug' -> die( message
=> "Problem number $i does not exist!" );
364 # }}} shrinkage_stats
368 =head2 wres_shrinkage
374 my $wres_shrink = $model_object -> wres_shrinkage();
380 Calculates wres shrinkage, a table file with wres is necessary. The
381 return value is reference of and array with one an array per problem
388 my @problems = @
{$self -> {'problems'}};
389 foreach my $problem ( @problems ) {
390 push( @wres_shrinkage, $problem -> wres_shrinkage
);
405 my $eta_shrink = $model_object -> eta_shrinkage();
411 Calculates eta shrinkage, a table file with eta is necessary. The
412 return value is reference of and array with one an array per problem
419 my @problems = @
{$self -> {'problems'}};
420 foreach my $problem ( @problems ) {
421 push( @eta_shrinkage, $problem -> eta_shrinkage
);
428 # {{{ nonparametric_code
430 start nonparametric_code
432 if ( $#problem_numbers > 0 and $#enabled > 0 ){
433 if ( $#problem_numbers != $#enabled ) {
434 'debug' -> die( message
=> "The number of problem_numbers ".($#problem_numbers+1).
435 "and enabled/disabled nonparametric_code ".($#enabled+1).
439 unless( $#problem_numbers > 0 ){
440 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
442 my @problems = @
{$self -> {'problems'}};
444 foreach my $i ( @problem_numbers ) {
445 if ( defined $problems[ $i-1 ] ) {
446 if ( defined $enabled[ $j ] ) {
447 $problems[ $i-1 ] -> nonparametric_code
( $enabled[ $j ] );
449 push( @indicators, $problems[ $i-1 ] -> nonparametric_code
);
452 'debug' -> die( message
=> "Problem number $i does not exist!" );
457 end nonparametric_code
459 # }}} nonparametric_code
461 # {{{ add_nonparametric_code
463 start add_nonparametric_code
465 $self -> set_records
( type
=> 'nonparametric',
466 record_strings
=> [ 'MARGINALS UNCONDITIONAL' ] );
467 $self -> set_option
( record_name
=> 'estimation',
468 option_name
=> 'POSTHOC' );
469 my ( $msfo_ref, $junk ) = $self ->
470 _get_option_val_pos
( name
=> 'MSFO',
471 record_name
=> 'estimation' );
472 my @nomegas = @
{$self -> nomegas
};
474 for( my $i = 0; $i <= $#nomegas; $i++ ) { # loop the problems
476 for( my $j = 0; $j <= $nomegas[$i]; $j++ ) {
477 $marg_str = $marg_str.' COM('.($j+1).')=MG'.($j+1);
479 $marg_str = $marg_str.' FILE='.$self->filename.'.marginals'.
480 ' NOAPPEND ONEHEADER NOPRINT';
481 $self -> add_records
( problem_numbers
=> [($i+1)],
483 record_strings
=> [ $marg_str ] );
484 $self -> remove_option
( record_name
=> 'abbreviated',
485 option_name
=> 'COMRES' );
486 $self -> add_option
( record_name
=> 'abbreviated',
487 option_name
=> 'COMRES',
488 option_value
=> ($nomegas[$i]+1),
489 add_record
=> 1 ); #Add $ABB if not existing
491 $self -> add_marginals_code
( problem_numbers
=> [($i+1)],
492 nomegas
=> [ $nomegas[$i] ] );
495 if( not defined $msfo_ref ) {
496 for( my $i = 0; $i < $self -> nproblems
; $i++ ) {
497 $self -> add_option
( record_name
=> 'estimation',
498 option_name
=> 'MSFO',
499 option_value
=> $self -> filename
.'.msfo'.($i+1) );
502 for( my $i = 0; $i < scalar @
{$msfo_ref}; $i++ ) {
503 if( not defined $msfo_ref->[$i] or not defined $msfo_ref->[$i][0] ) {
504 $self -> add_option
( record_name
=> 'estimation',
505 option_name
=> 'MSFO',
506 option_value
=> $self -> filename
.'.msfo'.($i+1) );
511 end add_nonparametric_code
513 # }}} add_nonparametric_code
523 $model_object -> flush_data();
529 flush data calls the same method on each data object (usually one)
530 which causes it to write data to disk and remove its data from memory.
536 if ( defined $self -> {'datas'} ) {
537 foreach my $data ( @
{$self -> {'datas'}} ) {
552 C<< my $file_name = $model_object -> full_name(); >>
556 full_name will return the name of the modelfile and its directory in a
557 string. For example: "/users/guest/project/model.mod".
563 $full_name = $self -> {'directory'} . $self -> {'filename'};
571 This function is unused
and should probably be removed
.
573 # start __sync_output
575 unless( defined $self -> {'outputfile'} ){
576 'debug' -> die( message
=> "No output file is set, cannot synchronize output" );
578 @
{$self -> {'outputs'}} = ();
579 push ( @
{$self -> {'outputs'}}, output
->
580 new
( filename
=> $self -> {'outputfile'},
581 ignore_missing_files
=> $self -> {'ignore_missing_files'},
582 target
=> $self -> {'target'},
583 model_id
=> $self -> {'model_id'} ) );
589 # {{{ add_marginals_code
591 start add_marginals_code
593 # add_marginals_code takes two arguments.
595 # - problem_numbers is an array holding the numbers of the problems in
596 # which code should be added.
598 # - nomegas which is an array holding the number of (diagonal-element)
599 # omegas of each problem given by problem_numbers.
601 # For each omega in each problem, verbatim code is added to make the
602 # marginals available for printing (e.g. to a table file). COM(1) will
603 # hold the nonparametric density, COM(2) the marginal cumulative value
604 # for the first eta, COM(2) the marginal cumulative density for the
605 # second eta and so on.
607 unless( $#problem_numbers >= 0 ){
608 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
611 my @problems = @
{$self -> {'problems'}};
613 foreach my $i ( @problem_numbers ) {
614 if ( defined $problems[ $i-1 ] ) {
615 $problems[$i-1] -> add_marginals_code
( nomegas
=> $nomegas[ $j ] );
617 'debug' -> die( message
=> "Problem number $i does not exist.");
622 end add_marginals_code
624 # }}} add_marginals_code
634 $model_object -> add_records( type => 'THETA',
635 record_strings => ['(0.1,15,23)'] );
651 =item problem_numbers
659 add_records is used to add NONMEM control file records to the model
660 object. The "type" argument is mandatory and must be a valid NONMEM
661 record name, such as "PRED" or "THETA". Otherwise an error will be
662 output and the program terminated (this is object to change, ideally
663 we would only report an error and let the caller deal with it). The
664 "record_strings" argument is a mandatory array of valid NONMEM record
665 code. Each array corresponds to a line of the record code. There
666 "problem_numbers" argument is optional and is an array of problems
667 numbered from 1 for which the record is added, by default the record
668 is added to all problems.
670 Notice that the records are appended to those that allready exists,
671 which makes sence for records that do not exist and for initial
672 values. For records like "DATA" or "PRED" you probably want to use
679 unless( $#problem_numbers >= 0 ){
680 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
683 my @problems = @
{$self -> {'problems'}};
684 foreach my $i ( @problem_numbers ) {
685 if ( defined $problems[ $i-1 ] ) {
686 # if( defined $self -> {'problems'} ){
687 # if( defined @{$self -> {'problems'}}[$problem_number - 1] ){
688 # my $problem = @{$self -> {'problems'}}[$problem_number - 1];
689 # $problem -> add_records( 'type' => $type,
690 # 'record_strings' => \@record_strings );
691 $problems[$i-1] -> add_records
( 'type' => $type,
692 'record_strings' => \
@record_strings );
694 'debug' -> die( message
=> "Problem number $i does not exist.");
698 # 'debug' -> die( message => "Model -> add_records: No Problems in model object.") ;
713 $model_object -> set_records( type => 'THETA',
714 record_strings => ['(0.1,15,23)'] );
730 =item problem_numbers
738 set_records works just like add_records but will replace any existing
739 records in the model object.
745 unless( $#problem_numbers >= 0 ){
746 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
749 my @problems = @
{$self -> {'problems'}};
750 foreach my $i ( @problem_numbers ) {
751 if ( defined $problems[ $i-1 ] ) {
752 # if( defined $self -> {'problems'} ){
753 # if( defined @{$self -> {'problems'}}[$problem_number - 1] ){
754 # my $problem = @{$self -> {'problems'}}[$problem_number - 1];
755 # $problem -> set_records( 'type' => $type,
756 # 'record_strings' => \@record_strings );
757 $problems[$i-1] -> set_records
( 'type' => $type,
758 'record_strings' => \
@record_strings );
760 'debug' -> die( message
=> "Problem number $i does not exist." );
764 # 'debug' -> die( "No Problems in model object.") ;
773 =head2 remove_records
779 $model_object -> remove_records( type => 'THETA' )
791 =item problem_numbers
799 remove_records removes the record given in the "type" argument which
800 must be a valid NONMEM record name.
806 unless( $#problem_numbers >= 0 ){
807 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
810 my @problems = @
{$self -> {'problems'}};
811 foreach my $i ( @problem_numbers ) {
812 if ( defined $problems[ $i-1 ] ) {
813 # if( defined $self -> {'problems'} ){
814 # if( defined @{$self -> {'problems'}}[$problem_number - 1] ){
815 # my $problem = @{$self -> {'problems'}}[$problem_number - 1];
816 # $problem -> remove_records( 'type' => $type );
817 $problems[$i-1] -> remove_records
( 'type' => $type );
819 'debug' -> die( message
=> "Problem number $i, does not exist" );
823 # 'debug' -> die( message => "No Problems in model object." );
838 $model_object -> copy( filename => 'copy.mod',
864 =item data_file_names
870 string with value 'disk' or 'mem'
872 =item extra_data_file_names
876 =item update_shrinkage_tables
884 copy produces a new modelfile object and a new file on disk whose name
885 is given by the "filename" argument. To create copies of data file the
886 copy_data options may be set to 1. The values of "data_file_names",
887 unless given, will be the model file name but with '.mod' exchanged
888 for '_$i.dta', where $i is the problem number. If data is not copied,
889 a new data object will be intialized from the same data file as the
890 previous model and "data_file_names" WILL BE IGNORED. This has the
891 side effect that the data file can be modified from both the original
892 model and the copy. The same holds for "extra_data_files". It is
893 possible to set "copy_output" to 1 as well, which then copies the
894 output object instead of reading the output file from disk, which is
895 slower. Since output objects are meant to be read-only, no
896 output_filename can be specified and the output object copy will
897 reside in memory only.
899 The "target" option has no effect.
905 # PP_TODO fix a nice copying of modelfile data
906 # preferably in memory copy. Perhaps flush data ?
908 # Check sanity of the length of data file names argument
909 if ( scalar @data_file_names > 0 ) {
910 'debug' -> die( message
=> "model -> copy: The number of specified new data file " .
911 "names ". scalar @data_file_names. "must\n match the number".
912 " of data objects connected to the model object".
913 scalar @
{$self -> {'datas'}} )
914 unless ( scalar @data_file_names == scalar @
{$self -> {'datas'}} );
917 ($d_filename = $filename) =~ s/\.mod$//;
918 for ( my $i = 1; $i <= scalar @
{$self -> {'datas'}}; $i++ ) {
919 # Data filename is created in this directory (no directory needed).
920 push( @data_file_names, $d_filename."_data_".$i."_copy.dta" );
924 # Check sanity of the length of extra_data file names argument
925 if ( scalar @extra_data_file_names > 0 ) {
926 'debug' -> die( message
=> "The number of specified new extra_data file ".
927 "names ". scalar @extra_data_file_names, "must\n match the number".
928 " of problems (one extra_data file per prolem)".
929 scalar @
{$self -> {'extra_data_files'}} )
930 unless( scalar @extra_data_file_names == scalar @
{$self -> {'extra_data_files'}} );
932 if ( defined $self -> {'extra_data_files'} ) {
934 ($d_filename = $filename) =~ s/\.mod$//;
935 for ( my $i = 1; $i <= scalar @
{$self -> {'extra_data_files'}}; $i++ ) {
936 # Extra_Data filename is created in this directory (no directory needed).
937 push( @extra_data_file_names, $d_filename."_extra_data_".$i."_copy.dta" );
942 ($directory, $filename) = OSspecific
::absolute_path
( $directory, $filename );
946 # save references to own data and output objects
947 my $datas = $self -> {'datas'};
948 # $Data::Dumper::Maxdepth = 2;
949 # die "MC1: ", Dumper $datas -> [0] -> {'individuals'};
950 my $outputs = $self -> {'outputs'};
952 my @problems = @
{$self -> {'problems'}};
953 for ( my $i = 0; $i <= $#problems; $i++ ) {
954 if ( defined $problems[$i] -> {'extra_data'} ) {
955 $extra_datas{$i} = $problems[$i] -> {'extra_data'};
959 my ( @new_datas, @new_extra_datas, @new_outputs );
961 $self -> synchronize
if not $self -> {'synced'};
963 # remove ref to data and output object to speed up the
965 $self -> {'datas'} = undef;
966 $self -> {'outputs'} = undef;
967 for ( my $i = 0; $i <= $#problems; $i++ ) {
968 $problems[$i] -> {'extra_data'} = undef;
971 # Copy the data objects if so is requested
972 if ( defined $datas ) {
974 foreach my $data ( @
{$datas} ) {
975 if ( $copy_data == 1 ) {
976 push( @new_datas, $data ->
977 copy
( filename
=> $data_file_names[$i]) );
979 # This line assumes one data per problem! May be a source of error.
980 my ( $cont_column, $wrap_column ) = $self -> problems
-> [$i] -> cont_wrap_columns
;
981 my $ignoresign = defined $self -> ignoresigns ?
$self -> ignoresigns
-> [$i] : undef;
982 my @model_header = @
{$self -> problems
-> [$i] -> header
};
983 push @new_datas, data
->
984 new
( filename
=> $data -> filename
,
985 directory
=> $data -> directory
,
986 cont_column
=> $cont_column,
987 wrap_column
=> $wrap_column,
988 #model_header => \@model_header,
990 ignoresign
=> $ignoresign,
991 idcolumn
=> $data -> idcolumn
);
997 # Copy the extra_data objects if so is requested
998 for ( my $i = 0; $i <= $#problems; $i++ ) {
999 my $extra_data = $extra_datas{$i};
1000 if ( defined $extra_data ) {
1001 if ( $copy_data == 1 ) {
1002 push( @new_extra_datas, $extra_data ->
1003 copy
( filename
=> $extra_data_file_names[$i]) );
1005 push( @new_extra_datas, extra_data
->
1006 new
( filename
=> $extra_data -> filename
,
1007 directory
=> $extra_data -> directory
,
1009 idcolumn
=> $extra_data -> idcolumn
) );
1015 # Clone self into new model object and set synced to 0 for
1017 $new_model = Storable
::dclone
( $self );
1018 $new_model -> {'synced'} = 0;
1020 # $Data::Dumper::Maxdepth = 3;
1021 # die Dumper $new_datas[0] -> {'individuals'};
1023 # Restore the data and output objects for self
1024 $self -> {'datas'} = $datas;
1025 $self -> {'outputs'} = $outputs;
1026 for ( my $i = 0; $i <= $#problems; $i++ ) {
1027 if( defined $extra_datas{$i} ){
1028 $problems[$i] -> {'extra_data'} = $extra_datas{$i};
1032 # Set the new file name for the copy
1033 $new_model -> directory
( $directory );
1034 $new_model -> filename
( $filename );
1036 # {{{ update the shrinkage modules
1038 my @problems = @
{$new_model -> problems
};
1039 for( my $i = 1; $i <= scalar @problems; $i++ ) {
1040 $problems[ $i-1 ] -> shrinkage_module
-> model
( $new_model );
1043 # }}} update the shrinkage modules
1045 # Copy the output object if so is requested (only one output
1046 # object defined per model object)
1047 if ( defined $outputs ) {
1048 foreach my $output ( @
{$outputs} ) {
1049 if ( $copy_output == 1 ) {
1050 push( @new_outputs, $output -> copy
);
1052 my $new_out = $filename;
1053 if( $new_out =~ /\.mod$/ ) {
1054 $new_out =~ s/\.mod$/\.lst/;
1056 $new_out = $new_out.'.lst';
1058 push( @new_outputs, output
->
1059 new
( filename
=> $new_out,
1060 directory
=> $directory,
1062 ignore_missing_files
=> 1,
1063 model_id
=> $new_model -> {'model_id'} ) );
1068 # Add the copied data and output objects to the model copy
1069 $new_model -> datas
( \
@new_datas );
1071 if ( $#new_extra_datas >= 0 ) {
1072 my @new_problems = @
{$new_model -> problems
};
1073 for ( my $i = 0; $i <= $#new_problems; $i++ ) {
1074 $new_problems[$i] -> {'extra_data'} = $new_extra_datas[$i];
1075 if ( $copy_data == 1 ){
1076 $new_problems[$i] -> {'extra_data_file_name'} = $extra_data_file_names[$i];
1081 $new_model -> {'outputs'} = \
@new_outputs;
1083 $new_model -> _write
;
1085 $new_model -> synchronize
if $target eq 'disk';
1099 my $indicators = $model_object -> covariance( enabled => [1] );
1111 =item problem_numbers
1119 covariance will let you turn the covariance step on and off per
1120 problem. The "enabled" argument is an array which must have a length
1121 equal to the number of problems. Each element set to 0 will disable
1122 the covariance step for the corresponding problem. And conversely each
1123 element set to nonzero will enable the covariance step.
1125 covariance will return an array with an element for each problem, the
1126 element will indicate whether the covariance step is turned on or not.
1132 if ( $#problem_numbers > 0 ){
1133 if ( $#problem_numbers != $#enabled ) {
1134 'debug' -> die( message
=> "The number of problem_numbers ".($#problem_numbers+1).
1135 "and enabled/disabled covariance records ".($#enabled+1).
1139 unless( $#problem_numbers > 0 ){
1140 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
1142 my @problems = @
{$self -> {'problems'}};
1144 foreach my $i ( @problem_numbers ) {
1145 if ( defined $problems[ $i-1 ] ) {
1146 if ( defined $enabled[ $j ] ) {
1147 $problems[ $i-1 ] -> covariance
( enabled
=> $enabled[ $j ] );
1149 push( @indicators, $problems[ $i-1 ] -> covariance
);
1152 'debug' -> die( message
=> "Problem number $i does not exist!" );
1169 $model_object -> datas( [$data_obj] );
1171 my $data_objects = $model_object -> data;
1177 The argument is an unnamed array of data objects.
1181 If data is used without argument the data objects connected to the
1182 model object is returned. If an argument is given it must be an array
1183 of length equal to the number of problems with data objects. Those
1184 objects will replace any existing data objects and their filenames
1185 will be put in the model files records.
1191 my $nprobs = scalar @
{$self -> {'problems'}};
1192 if ( defined $parm ) {
1193 if ( ref($parm) eq 'ARRAY' ) {
1194 my @new_datas = @
{$parm};
1195 # Check that new_headers and problems match
1196 'debug' -> die( message
=> "The number of problems $nprobs and".
1197 " new data ". ($#new_datas+1) ." don't match in ".
1198 $self -> full_name
) unless ( $#new_datas + 1 == $nprobs );
1199 if ( defined $self -> {'problems'} ) {
1200 for( my $i = 0; $i < $nprobs; $i++ ) {
1201 $self -> _option_name
( position
=> 0,
1203 problem_number
=> $i+1,
1204 new_name
=> $new_datas[$i] -> filename
);
1207 'debug' -> die( message
=> "No problems defined in ".
1208 $self -> full_name
);
1211 'debug' -> die( message
=> "Supplied new value is not an array" );
1222 # I have removed this because it was only used in the bootstrap. I
1223 # fixed the bootstrap to use datafiles instead. Also the bootstrap
1224 # methods who used this was very old and should probably be removed as
1229 # datafile either retrieves or sets a new name for the datafile in the first problem of the
1230 # model. This method is only here for compatibility reasons. Don't use it. Use L</datafiles> instead.
1232 if( defined $new_name ){
1233 $self -> _option_name
( position
=> 0,
1235 problem_number
=> $problem_number,
1236 new_name
=> $new_name);
1237 my ( $cont_column, $wrap_column ) = $self -> problems
-> [$problem_number-1] ->
1239 my $ignoresign = defined $self -> ignoresigns ?
1240 $self -> ignoresigns
-> [$problem_number-1] : undef;
1241 my @model_header = @
{$self -> problems
-> [$problem_number-1] -> header
};
1242 $self -> {'datas'} -> [$problem_number-1] = data
->
1243 new
( idcolumn
=> $self -> idcolumn
( problem_number
=> $problem_number ),
1244 ignoresign
=> $ignoresign,
1245 filename
=> $new_name,
1246 cont_column
=> $cont_column,
1247 wrap_column
=> $wrap_column,
1248 #model_header => \@model_header,
1249 ignore_missing_files
=> $self -> {'ignore_missing_files'},
1250 target
=> $self -> {'target'} );
1252 $name = $self -> _option_name
( position
=> 0, record
=> 'data', problem_number
=> $problem_number );
1267 $model_object -> datafiles( new_names => ['datafile.dta'] );
1279 =item problem_numbers
1291 datafiles changes the names of the data files in a model file. The
1292 "new_names" argument is an array of strings, where each string gives
1293 the file name of a problem data file. The length of "new_names" must
1294 be equal to the "problem_numbers" argument. "problem_numbers" is by
1295 default containing all of the models problems numbers. In the example
1296 above we only have one problem in the model file and therefore only
1297 need to give on new file name.
1299 Unless new_names is given datafiles returns the names of the data
1300 files used by the model file. If the optional "absolute_path" argument
1301 is given, the returned file names will have the path to file as well.
1307 # The datafiles method retrieves or sets the names of the
1308 # datafiles specified in the $DATA record of each problem. The
1309 # problem_numbers argument can be used to control which
1310 # problem that is affected. If absolute_path is set to 1, the
1311 # returned file names are given with absolute paths.
1313 unless( $#problem_numbers > 0 ){
1314 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
1316 if ( scalar @new_names > 0 ) {
1318 my @idcolumns = @
{$self ->
1319 idcolumns
( problem_numbers
=> \
@problem_numbers )};
1320 foreach my $new_name ( @new_names ) {
1321 if ( $absolute_path ) {
1323 ($tmp, $new_name) = OSspecific
::absolute_path
('', $new_name );
1324 $new_name = $tmp . $new_name;
1327 $self -> _option_name
( position
=> 0,
1329 problem_number
=> $problem_numbers[$i],
1330 new_name
=> $new_name);
1331 my ( $cont_column, $wrap_column ) = $self -> problems
->
1332 [$problem_numbers[$i]-1] -> cont_wrap_columns
;
1333 my $ignoresign = defined $self -> ignoresigns ?
$self -> ignoresigns
-> [$i] : undef;
1334 my @model_header = @
{$self -> problems
-> [$i] -> header
};
1335 $self -> {'datas'} -> [$problem_numbers[$i]-1] = data
->
1336 new
( idcolumn
=> $idcolumns[$i],
1337 ignoresign
=> $ignoresign,
1338 filename
=> $new_name,
1339 cont_column
=> $cont_column,
1340 wrap_column
=> $wrap_column,
1341 #model_header => \@model_header,
1342 ignore_missing_files
=> $self -> {'ignore_missing_files'},
1343 target
=> $self -> {'target'} );
1347 foreach my $prob_num ( @problem_numbers ) {
1348 if ( $absolute_path ) {
1349 my ($d_dir, $d_name);
1351 OSspecific
::absolute_path
($self -> {'directory'}, $self ->_option_name( position
=> 0,
1353 problem_number
=> $prob_num ) );
1354 push( @names, $d_dir . $d_name );
1356 my $name = $self -> _option_name
( position
=> 0,
1358 problem_number
=> $prob_num );
1359 $name =~ s/.*[\/\\]//;
1360 push( @names, $name );
1372 # This method is renamed __des in dia but not here. If nothing broke
1373 # until now I think we can safely remove it.
1377 # Returns the des part specified subproblem.
1378 # TODO: Even though new_des can be specified, they wont be set
1381 my @prob = @
{$self -> problems
};
1382 my @des = @
{$prob[$problem_number - 1] -> get_record
('des') -> code
}
1383 if ( defined $prob[$problem_number - 1] -> get_record
('des') );
1392 $self -> {'problems'} -> [0] -> eigen
;
1400 # This method is renamed __error in dia but not here. If nothing broke
1401 # until now I think we can safely remove it.
1407 # @error = $modelObject -> error;
1409 # Returns the error part specified subproblem.
1410 # TODO: Even though new_error can be specified, they wont be set
1412 my @prob = @
{$self -> problems
};
1413 my @error = @
{$prob[0] -> get_record
('error') -> code
}
1414 if ( defined $prob[0] -> get_record
('error') );
1420 # {{{ extra_data_files
1422 =head2 extra_data_files
1428 $model_object -> extra_data_files( ['extra_data.dta'] );
1430 my $extra_file_name = $model_object -> extra_data_files;
1436 The argument is an unnamed array of strings
1440 If extra_data_files is used without argument the names of any extra
1441 data files connected to the model object is returned. If an argument
1442 is given it must be an array of length equal to the number of problems
1443 in the model. Then the names of the extra data files will be changed
1444 to those in the array.
1448 start extra_data_files
1451 # Sets or retrieves extra_data_file_name on problem level
1452 my $nprobs = scalar @
{$self -> {'problems'}};
1453 if ( defined $parm ) {
1454 if ( ref($parm) eq 'ARRAY' ) {
1455 my @new_file_names = @
{$parm};
1456 # Check that new_file_names and problems match
1457 'debug' -> die( message
=> "model -> extra_data_files: The number of problems $nprobs and" .
1458 " new_file_names " . $#new_file_names+1 . " don't match in ".
1459 $self -> full_name
) unless ( $#new_file_names + 1 == $nprobs );
1460 if ( defined $self -> {'problems'} ) {
1461 for( my $i = 0; $i < $nprobs; $i++ ) {
1462 $self -> {'problems'} -> [$i] -> extra_data_file_name
( $new_file_names[$i] );
1465 'debug' -> die( message
=> "No problems defined in " .
1466 $self -> full_name
);
1469 'debug' -> die(message
=> "Supplied new value is not an array.");
1472 if ( defined $self -> {'problems'} ) {
1473 for( my $i = 0; $i < $nprobs; $i++ ) {
1474 if( defined $self -> {'problems'} -> [$i] -> extra_data_file_name
) {
1475 push ( @file_names ,$self -> {'problems'} -> [$i] -> extra_data_file_name
);
1480 return \
@file_names;
1482 end extra_data_files
1486 # {{{ extra_data_headers
1488 =head2 extra_data_headers
1494 $model_object -> extra_data_headers( [$data_obj] );
1496 my $data_objects = $model_object -> extra_data_headers;
1502 The argument is an unnamed array of arrays of strings.
1506 If extra_data_files is used without argument the headers of any extra
1507 data files connected to the model object is returned. If an argument
1508 is given it must be an array of length equal to the number of problems
1509 in the model. Then the headers of the extra data files will be changed
1510 to those in the array.
1514 start extra_data_headers
1517 # Sets or retrieves extra_data_header on problem level
1518 my $nprobs = scalar @
{$self -> {'problems'}};
1519 if ( defined $parm ) {
1520 if ( ref($parm) eq 'ARRAY' ) {
1521 my @new_headers = @
{$parm};
1522 # Check that new_headers and problems match
1523 'debug' -> die( message
=> "The number of problems $nprobs and".
1524 " new_headers " . $#new_headers+1 . " don't match in ".
1525 $self -> full_name
) unless ( $#new_headers + 1 == $nprobs );
1526 if ( defined $self -> {'problems'} ) {
1527 for( my $i = 0; $i < $nprobs; $i++ ) {
1528 $self -> {'problems'} -> [$i] -> extra_data_header
( $new_headers[$i] );
1531 'debug' -> die( message
=> "No problems defined in " . $self -> full_name
);
1534 'debug' -> die( message
=> "Supplied new value is not an array" );
1537 if ( defined $self -> {'problems'} ) {
1538 for( my $i = 0; $i < $nprobs; $i++ ) {
1539 push ( @headers, $self -> {'problems'} -> [$i] -> extra_data_header
);
1545 end extra_data_headers
1547 # }}} extra_data_headers
1557 my $factors = $model_object -> factors;
1573 =item problem_number
1577 =item return_occurences
1581 =item unique_in_individual
1589 The following text comes from the documentation of
1590 data::factors. model::factors will call data::factors for the given
1591 problem number in the model object. Also it will take try to find
1592 "column_head" in the $INPUT record instead of the data file header.
1594 Either column (number, starting at 1) or column_head must be
1595 specified. The default behaviour is to return a hash with the factors
1596 as keys referencing arrays with the order numbers (not the ID numbers)
1597 of the individuals that contain this factor.
1599 If unique_in_individual is true (1), the returned hash will contain an
1600 element with key 'Non-unique values found' and value 1 if any
1601 individual contain more than one value in the specified column.
1603 Return occurences will calculate the occurence of each factor
1604 value. Several occurences in one individual counts as one
1605 occurence. The elements of the returned hash will have the factors as
1606 keys and the number of occurences as values.
1612 # Calls <I>factors</I> on the data object of a specified
1613 # problem. See <I>data -> factors</I> for details.
1615 my $extra_data_column;
1616 if ( defined $column_head ) {
1617 # Check normal data object first
1618 my ( $values_ref, $positions_ref ) = $self ->
1619 _get_option_val_pos
( problem_numbers
=> [$problem_number],
1620 name
=> $column_head,
1621 record_name
=> 'input',
1622 global_position
=> 1 );
1623 $column_number = $positions_ref -> [0];
1624 # Next, check extra_data
1625 my $extra_data_headers = $self -> extra_data_headers
;
1626 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
1627 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
1628 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
1631 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
1632 unless ( defined $column_number or defined $extra_data_column );
1634 $column_number = $column;
1636 if ( defined $column_number) {
1637 %factors = %{$self -> {'datas'} -> [$problem_number-1] ->
1638 factors
( column
=> $column_number,
1639 unique_in_individual
=> $unique_in_individual,
1640 return_occurences
=> $return_occurences )};
1642 %factors = %{$self -> {'problems'} -> [$problem_number-1] -> extra_data
1643 -> factors
( column
=> $extra_data_column,
1644 unique_in_individual
=> $unique_in_individual,
1645 return_occurences
=> $return_occurences )};
1660 my $fractions = $model_object -> fractions;
1676 =item problem_number
1680 =item return_occurences
1684 =item ignore_missing
1692 fractions will return the fractions from data::fractions. It will find
1693 "column_head" in the $INPUT record instead of that data header as
1694 data::fractions does.
1700 # Calls <I>fractions</I> on the data object of a specified
1701 # problem. See <I>data -> fractions</I> for details.
1703 my $extra_data_column;
1704 if ( defined $column_head ) {
1705 # Check normal data object first
1706 my ( $values_ref, $positions_ref ) = $self ->
1707 _get_option_val_pos
( problem_numbers
=> [$problem_number],
1708 name
=> $column_head,
1709 record_name
=> 'input',
1710 global_position
=> 1 );
1711 $column_number = $positions_ref -> [0];
1712 # Next, check extra_data
1713 my $extra_data_headers = $self -> extra_data_headers
;
1714 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
1715 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
1716 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
1719 'debug' -> die( "Unknown column \"$column_head\"" )
1720 unless ( defined $column_number or defined $extra_data_column );
1722 $column_number = $column;
1724 if ( defined $column_number) {
1725 %fractions = %{$self -> {'datas'} -> [$problem_number-1] ->
1726 fractions
( column
=> $column_number,
1727 unique_in_individual
=> $unique_in_individual,
1728 ignore_missing
=> $ignore_missing )};
1730 %fractions = %{$self -> {'problems'} -> [$problem_number-1] -> extra_data
1731 -> fractions
( column
=> $extra_data_column,
1732 unique_in_individual
=> $unique_in_individual,
1733 ignore_missing
=> $ignore_missing )};
1748 my $fractions = $model_object -> fractions;
1764 =item problem_number
1768 =item return_occurences
1772 =item ignore_missing
1780 fractions will return the fractions from data::fractions. It will find
1781 "column_head" in the $INPUT record instead of that data header as
1782 data::fractions does.
1788 # Sets or gets the 'fixed' status of a (number of)
1789 # parameter(s). 1 correspond to a parameter being fixed and
1790 # 0 not fixed. The returned parameter is a reference to a
1791 # two-dimensional array, indexed by problems and parameter
1793 # Valid parameter types are 'theta', 'omega' and 'sigma'.
1795 @fixed = @
{ $self -> _init_attr
1796 ( parameter_type
=> $parameter_type,
1797 parameter_numbers
=> \
@parameter_numbers,
1798 problem_numbers
=> \
@problem_numbers,
1799 new_values
=> \
@new_values,
1800 attribute
=> 'fix')};
1806 # {{{ have_missing_data
1814 my $fractions = $model_object -> fractions;
1830 =item problem_number
1834 =item return_occurences
1838 =item ignore_missing
1846 fractions will return the fractions from data::fractions. It will find
1847 "column_head" in the $INPUT record instead of that data header as
1848 data::fractions does.
1852 start have_missing_data
1854 # Calls <I>have_missing_data</I> on the data object of a specified
1855 # problem. See <I>data -> have_missing_data</I> for details.
1857 my $extra_data_column;
1858 if ( defined $column_head ) {
1859 # Check normal data object first
1860 my ( $values_ref, $positions_ref ) = $self ->
1861 _get_option_val_pos
( problem_numbers
=> [$problem_number],
1862 name
=> $column_head,
1863 record_name
=> 'input',
1864 global_position
=> 1 );
1865 $column_number = $positions_ref -> [0];
1866 # Next, check extra_data
1867 my $extra_data_headers = $self -> extra_data_headers
;
1868 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
1869 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
1870 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
1873 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
1874 unless ( defined $column_number or defined $extra_data_column );
1876 $column_number = $column;
1878 if ( defined $column_number) {
1879 $return_value = $self -> {'datas'} -> [$problem_number-1] ->
1880 have_missing_data
( column
=> $column_number );
1882 $return_value = $self -> {'problems'} -> [$problem_number-1] ->
1883 extra_data
-> have_missing_data
( column
=> $extra_data_column );
1886 end have_missing_data
1898 my $fractions = $model_object -> fractions;
1914 =item problem_number
1918 =item return_occurences
1922 =item ignore_missing
1930 fractions will return the fractions from data::fractions. It will find
1931 "column_head" in the $INPUT record instead of that data header as
1932 data::fractions does.
1940 # @idcolumns = @{$modelObject -> idcolumns( problem_numbers => [2,3] );
1942 # idcolumns returns the idcolumn index in the datafile for the
1943 # specified problem.
1946 ( $junk_ref, $col ) = $self ->
1947 _get_option_val_pos
( name
=> 'ID',
1948 record_name
=> 'input',
1949 problem_numbers
=> [$problem_number] );
1951 if ( $problem_number ne 'all' ) {
1967 my $fractions = $model_object -> fractions;
1983 =item problem_number
1987 =item return_occurences
1991 =item ignore_missing
1999 fractions will return the fractions from data::fractions. It will find
2000 "column_head" in the $INPUT record instead of that data header as
2001 data::fractions does.
2009 # @column_numbers = @{$modelObject -> idcolumns( problem_numbers => [2] )};
2011 # idcolumns returns the idcolumn indexes in the datafile for the
2012 # specified problems.
2014 my ( $junk_ref, $col_ref ) = $self ->
2015 _get_option_val_pos
( name
=> 'ID',
2016 record_name
=> 'input',
2017 problem_numbers
=> \
@problem_numbers );
2018 # There should only be one instance of $INPUT and hence we collapse
2019 # the two-dim return from _get_option_pos_val to a one-dim array:
2021 foreach my $prob ( @
{$col_ref} ) {
2022 foreach my $inst ( @
{$prob} ) {
2023 push( @column_numbers, $inst );
2039 $model_object -> ignoresigns( ['#','@'] );
2041 my $ignoresigns = $model_object -> ignoresigns;
2047 The argument is an unnamed array of strings
2051 If ignoresigns is used without argument the string that specifies
2052 which string that is used for comment rows in the data file is
2053 returned. The returned value is an array including the ignore signs
2054 of each problem. If an argument is given it must be an array of
2055 length equal to the number of problems in the model. Then the names of
2056 the extra data files will be changed to those in the array.
2064 # @ignore_signs = @{$modelObject -> ignoresigns( problem_numbers => [2,4] )};
2066 # ignoresigns returns the ignore signs in the datafile for the
2067 # specified problems
2069 foreach my $prob ( @
{$self -> {'problems'}} ) {
2070 my @datarecs = @
{$prob -> datas
};
2071 if ( defined $datarecs[0] ) {
2072 push( @ignore, $datarecs[0] -> ignoresign
);
2074 push( @ignore, '#' );
2078 # print "IGNORE: @ignore\n";
2091 # @ignore_signs = @{$modelObject -> ignore_lists( problem_numbers => [2,4] )};
2093 # ignore_lists returns the ignore signs in the datafile for the
2094 # specified problems
2096 foreach my $prob ( @
{$self -> {'problems'}} ) {
2097 my @datarecs = @
{$prob -> datas
};
2098 if ( defined $datarecs[0] ) {
2099 push( @ignore, $datarecs[0] -> ignore_list
);
2101 push( @ignore, '#' );
2105 # print "IGNORE: @ignore\n";
2120 my $fractions = $model_object -> fractions;
2136 =item problem_number
2140 =item return_occurences
2144 =item ignore_missing
2152 fractions will return the fractions from data::fractions. It will find
2153 "column_head" in the $INPUT record instead of that data header as
2154 data::fractions does.
2162 # @indexArray = @{$modelObject -> indexes( 'parameter_type' => 'omega' )};
2164 # A call to I<indexes> returns the indexes of all parameters
2165 # specified in I<parameter_numbers> from the subproblems
2166 # specified in I<problem_numbers>. The method returns a reference to an array that has
2167 # the same structure as parameter_numbers but for each
2168 # array of numbers is instead an array of indices. The method
2169 # uses a method from the model::problem class to format the
2170 # indices, so here are a few lines from the code comments in
2171 # model/problem.pm that describes the returned value:
2174 # The Indexes method calculates the index for a
2175 # parameter. Off-diagonal elements will get a index 'i_j', where i
2176 # is the row number and j is the column number
2179 unless( $#problem_numbers > 0 ){
2180 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
2182 my @problems = @
{$self -> {'problems'}};
2183 foreach my $i ( @problem_numbers ) {
2184 if ( defined $problems[ $i-1 ] ) {
2186 $problems[ $i-1 ] ->
2187 indexes
( parameter_type
=> $parameter_type,
2188 parameter_numbers
=> $parameter_numbers[ $i-1 ] ) );
2190 'debug' -> die( message
=> "Problem number $i does not exist!" );
2198 # {{{ initial_values
2206 my $fractions = $model_object -> fractions;
2222 =item problem_number
2226 =item return_occurences
2230 =item ignore_missing
2238 fractions will return the fractions from data::fractions. It will find
2239 "column_head" in the $INPUT record instead of that data header as
2240 data::fractions does.
2244 start initial_values
2246 # initial_values either sets or gets the initial values of
2247 # the parameter specified in "parameter_type" for each
2248 # problem specified in problem_numbers. For each element
2249 # in problem_numbers there must be a reference in
2250 # parameter_numbers to an array that specify the indices
2251 # of the parameters in the subproblem for which the initial
2252 # values are set, replaced or retrieved.
2254 # The add_if_absent argument tells the method to add an init
2255 # (theta,omega,sigma) if the parameter number points to a
2256 # non-existing parameter with parameter number one higher
2257 # than the highest presently included. Only applicable if
2258 # new_values are set. Valid parameter types are 'theta',
2259 # 'omega' and 'sigma'.
2261 @initial_values = @
{ $self -> _init_attr
2262 ( parameter_type
=> $parameter_type,
2263 parameter_numbers
=> \
@parameter_numbers,
2264 problem_numbers
=> \
@problem_numbers,
2265 new_values
=> \
@new_values,
2266 attribute
=> 'init',
2267 add_if_absent
=> $add_if_absent )};
2271 # }}} initial_values
2282 my $fractions = $model_object -> fractions;
2298 =item problem_number
2302 =item return_occurences
2306 =item ignore_missing
2314 fractions will return the fractions from data::fractions. It will find
2315 "column_head" in the $INPUT record instead of that data header as
2316 data::fractions does.
2324 # if( $modelObject -> is_option_set( record => 'recordName', name => 'optionName' ) ){
2325 # print "problem_number 1 has option optionName set in record recordName";
2328 # is_option_set checks if an option is set in a given record in given problem.
2330 my ( @problems, @records, @options );
2331 my $accessor = $record.'s';
2332 if ( defined $self -> {'problems'} ) {
2333 @problems = @
{$self -> {'problems'}};
2335 'debug' -> die( message
=> "No problems defined in model" );
2337 unless( defined $problems[$problem_number - 1] ){
2338 'debug' -> warn( level
=> 2,
2339 message
=> "model -> is_option_set: No problem number $problem_number defined in model" );
2340 return 0; # No option can be set if no problem exists.
2343 if ( defined $problems[$problem_number - 1] -> $accessor ) {
2344 @records = @
{$problems[$problem_number - 1] -> $accessor};
2346 'debug' -> warn( level
=> 2,
2347 message
=> "model -> is_option_set: No record $record defined" .
2348 " in problem number $problem_number." );
2352 unless(defined $records[$instance - 1] ){
2353 'debug' -> warn( level
=> 2,
2354 message
=> "model -> is_option_set: No record instance number $instance defined in model." );
2358 if ( defined $records[$instance - 1] -> options
) {
2359 @options = @
{$records[$instance - 1] -> options
};
2361 'debug' -> warn( level
=> 2,
2362 message
=> "No option defined in record: $record in problem number $problem_number." );
2365 foreach my $option ( @options ) {
2366 $found = 1 if ( defined $option and $option -> name
eq $name );
2368 if( index( $name, $option -> name
) > -1 ){
2387 my $fractions = $model_object -> fractions;
2403 =item problem_number
2407 =item return_occurences
2411 =item ignore_missing
2419 fractions will return the fractions from data::fractions. It will find
2420 "column_head" in the $INPUT record instead of that data header as
2421 data::fractions does.
2429 # is_run returns true if the outputobject owned by the
2430 # modelobject has valid outpudata either in memory or on disc.
2431 if( defined $self -> {'outputs'} ){
2432 if( @
{$self -> {'outputs'}}[0] -> have_output
){
2451 my $fractions = $model_object -> fractions;
2467 =item problem_number
2471 =item return_occurences
2475 =item ignore_missing
2483 fractions will return the fractions from data::fractions. It will find
2484 "column_head" in the $INPUT record instead of that data header as
2485 data::fractions does.
2491 my $problems = $self -> {'problems'};
2492 if( defined $problems -> [$problem_number - 1] ) {
2493 my $problem = $problems -> [$problem_number - 1];
2494 # If we don't have an ESTIMATION record we are simulating.
2495 $is_sim = 1 unless( defined $problem -> {'estimations'} and
2496 scalar( @
{$problem-> {'estimations'}} ) > 0 );
2498 # If we have a ONLYSIM option in the simulation record.
2499 $is_sim = 1 if( $self -> is_option_set
( name
=> 'ONLYSIM',
2500 record
=> 'simulation',
2501 problem_number
=> $problem_number ));
2503 # If max evaluations is zero we are simulating
2504 $is_sim = 1 if( defined $self -> maxeval
(problem_numbers
=> [$problem_number]) and
2505 defined $self -> maxeval
(problem_numbers
=> [$problem_number])->[0][0] and
2506 $self -> maxeval
(problem_numbers
=> [$problem_number])->[0][0] == 0 );
2510 # If non of the above is true, we are estimating.
2512 'debug' -> warn( level
=> 1,
2513 message
=> 'Problem nr. $problem_number not defined. Assuming no simulation' );
2529 my $fractions = $model_object -> fractions;
2545 =item problem_number
2549 =item return_occurences
2553 =item ignore_missing
2561 fractions will return the fractions from data::fractions. It will find
2562 "column_head" in the $INPUT record instead of that data header as
2563 data::fractions does.
2569 # lower_bounds either sets or gets the initial values of the
2570 # parameter specified in the argument parameter_type for
2571 # each problem specified in problem_numbers. See L</fixed>.
2573 @lower_bounds = @
{ $self -> _init_attr
2574 ( parameter_type
=> $parameter_type,
2575 parameter_numbers
=> \
@parameter_numbers,
2576 problem_numbers
=> \
@problem_numbers,
2577 new_values
=> \
@new_values,
2578 attribute
=> 'lobnd')};
2592 my $fractions = $model_object -> fractions;
2608 =item problem_number
2612 =item return_occurences
2616 =item ignore_missing
2624 fractions will return the fractions from data::fractions. It will find
2625 "column_head" in the $INPUT record instead of that data header as
2626 data::fractions does.
2634 # @labels = @{$modobj -> labels( parameter_type => 'theta' )};
2636 # This basic usage takes one arguments and returns matched names and
2637 # estimated values of the specified parameter. The parameter_type argument
2638 # is mandatory. It returns the labels of all parameters of type given by
2640 # @labels will be a two-dimensional array:
2641 # [[label1][label2][label3]...]
2643 # $labels -> labels( parameter_type => 'theta',
2644 # problem_numbers => [2,4] );
2646 # To get labels of specific problems, the problem_numbers argument can be used.
2647 # It should be a reference to an array containing the numbers
2648 # of all problems whos labels should be retrieved.
2650 # $modobj -> labels( parameter_type => 'theta',
2651 # problem_numbers => [2,4],
2652 # parameter_numbers => [[1,3][4,6]]);
2654 # The retrieval can be even more specific by using the parameter_numbers
2655 # argument. It should be a reference to a two-dimensional array, where
2656 # the inner arrays holds the numbers of the parameters that should be
2657 # fetched. In the example above, parameters one and three from problem two
2658 # plus parameters four and six from problem four are retrieved.
2660 # $modobj -> labels( parameter_type => 'theta',
2661 # problem_numbers => [2,4],
2662 # parameter_numbers => [[1,3][4,6]],
2665 # To get generic labels for the parameters - e.g. OM1, OM2_1, OM2 etc -
2666 # set the generic argument to 1.
2668 # $modobj -> labels( parameter_type => 'theta',
2669 # problem_numbers => [2],
2670 # parameter_numbers => [[1,3]],
2671 # new_values => [['Volume','Clearance']] );
2673 # The new_values argument can be used to give parameters new labels. In
2674 # the above example, parameters one and three in problem two are renamed
2675 # Volume and Clearance.
2678 my ( @index, $idx );
2679 @labels = @
{ $self -> _init_attr
2680 ( parameter_type
=> $parameter_type,
2681 parameter_numbers
=> \
@parameter_numbers,
2682 problem_numbers
=> \
@problem_numbers,
2683 new_values
=> \
@new_values,
2684 attribute
=> 'label' )};
2686 # foreach my $prl ( @labels ) {
2687 # foreach my $label ( @{$prl} ) {
2688 # print "Label: $label\n";
2693 @index = @
{$self -> indexes
( parameter_type
=> $parameter_type,
2694 parameter_numbers
=> \
@parameter_numbers,
2695 problem_numbers
=> \
@problem_numbers )};
2697 for ( my $i = 0; $i <= $#labels; $i++ ) {
2698 for ( my $j = 0; $j < scalar @
{$labels[$i]}; $j++ ) {
2699 $idx = $index[$i][$j];
2700 $labels[$i][$j] = uc(substr($parameter_type,0,2)).$idx
2701 unless ( defined $labels[$i][$j] and not $generic );
2717 my $fractions = $model_object -> fractions;
2733 =item problem_number
2737 =item return_occurences
2741 =item ignore_missing
2749 fractions will return the fractions from data::fractions. It will find
2750 "column_head" in the $INPUT record instead of that data header as
2751 data::fractions does.
2759 # @maxev = @{$modobj -> maxeval};
2761 # This basic usage takes no arguments and returns the value of the
2762 # MAXEVAL option in the $ESTIMATION record of each problem.
2763 # @maxev will be a two dimensional array:
2764 # [[maxeval_prob1][maxeval_prob2][maxeval_prob3]...]
2766 # $modobj -> maxeval( new_values => [[0],[999]];
2768 # If the new_values argument of maxeval is given, the values of the
2769 # MAXEVAL options will be changed. In this example, MAXEVAL will be
2770 # set to 0 in the first problem and to 999 in the second.
2771 # The number of elements in new_values must match the number of problems
2772 # in the model object $modobj.
2774 # $modobj -> maxeval( new_values => [[0],[999]],
2775 # problem_numbers => [2,4] );
2777 # To set the MAXEVAL of specific problems, the problem_numbers argument can
2778 # be used. It should be a reference to an array containing the numbers
2779 # of all problems where the MAXEVAL should be changed or retrieved.
2780 # If specified, the size of new_values must be the same as the size
2781 # of problem_numbers.
2786 my ( $val_ref, $junk ) = $self ->
2787 _option_val_pos
( name
=> 'MAX',
2788 record_name
=> 'estimation',
2789 problem_numbers
=> \
@problem_numbers,
2790 new_values
=> \
@new_values,
2791 exact_match
=> $exact_match );
2792 @values = @
{$val_ref};
2806 my $fractions = $model_object -> fractions;
2822 =item problem_number
2826 =item return_occurences
2830 =item ignore_missing
2838 fractions will return the fractions from data::fractions. It will find
2839 "column_head" in the $INPUT record instead of that data header as
2840 data::fractions does.
2846 # Calls <I>median</I> on the data object of a specified
2847 # problem. See <I>data -> median</I> for details.
2849 my $extra_data_column;
2850 if ( defined $column_head ) {
2851 # Check normal data object first
2852 my ( $values_ref, $positions_ref ) = $self ->
2853 _get_option_val_pos
( problem_numbers
=> [$problem_number],
2854 name
=> $column_head,
2855 record_name
=> 'input',
2856 global_position
=> 1 );
2857 $column_number = $positions_ref -> [0];
2858 if ( not defined $column_number ) {
2859 # Next, check extra_data
2860 my $extra_data_headers = $self -> extra_data_headers
;
2861 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
2862 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
2863 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
2867 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
2868 unless ( defined $column_number or defined $extra_data_column );
2870 $column_number = $column;
2873 if ( defined $column_number) {
2874 $median = $self -> {'datas'} -> [$problem_number-1] ->
2875 median
( column
=> $column_number,
2876 unique_in_individual
=> $unique_in_individual );
2878 $median = $self -> {'problems'} -> [$problem_number-1] -> extra_data
->
2879 median
( column
=> $extra_data_column,
2880 unique_in_individual
=> $unique_in_individual );
2895 my $fractions = $model_object -> fractions;
2911 =item problem_number
2915 =item return_occurences
2919 =item ignore_missing
2927 fractions will return the fractions from data::fractions. It will find
2928 "column_head" in the $INPUT record instead of that data header as
2929 data::fractions does.
2935 # Calls <I>max</I> on the data object of a specified
2936 # problem. See <I>data -> max</I> for details.
2938 my $extra_data_column;
2939 if ( defined $column_head ) {
2940 # Check normal data object first
2941 my ( $values_ref, $positions_ref ) = $self ->
2942 _get_option_val_pos
( problem_numbers
=> [$problem_number],
2943 name
=> $column_head,
2944 record_name
=> 'input',
2945 global_position
=> 1 );
2946 $column_number = $positions_ref -> [0];
2947 if ( not defined $column_number ) {
2948 # Next, check extra_data
2949 my $extra_data_headers = $self -> extra_data_headers
;
2950 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
2951 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
2952 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
2956 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
2957 unless ( defined $column_number or defined $extra_data_column );
2959 $column_number = $column;
2962 if ( defined $column_number) {
2963 $max = $self -> {'datas'} -> [$problem_number-1] ->
2964 max
( column
=> $column_number );
2966 $max = $self -> {'problems'} -> [$problem_number-1] -> extra_data
->
2967 max
( column
=> $extra_data_column );
2982 my $fractions = $model_object -> fractions;
2998 =item problem_number
3002 =item return_occurences
3006 =item ignore_missing
3014 fractions will return the fractions from data::fractions. It will find
3015 "column_head" in the $INPUT record instead of that data header as
3016 data::fractions does.
3022 # Calls <I>min</I> on the data object of a specified
3023 # problem. See <I>data -> min</I> for details.
3025 my $extra_data_column;
3026 if ( defined $column_head ) {
3027 # Check normal data object first
3028 my ( $values_ref, $positions_ref ) = $self ->
3029 _get_option_val_pos
( problem_numbers
=> [$problem_number],
3030 name
=> $column_head,
3031 record_name
=> 'input',
3032 global_position
=> 1 );
3033 $column_number = $positions_ref -> [0];
3034 if ( not defined $column_number ) {
3035 # Next, check extra_data
3036 my $extra_data_headers = $self -> extra_data_headers
;
3037 if ( defined $extra_data_headers and defined $extra_data_headers -> [0] ) {
3038 for ( my $i = 1; $i <= scalar @
{$extra_data_headers->[0]}; $i++ ) {
3039 $extra_data_column = $i if ( $column_head eq $extra_data_headers->[0][$i-1] );
3043 'debug' -> die( message
=> "Unknown column \"$column_head\"" )
3044 unless ( defined $column_number or defined $extra_data_column );
3046 $column_number = $column;
3049 if ( defined $column_number) {
3050 $min = $self -> {'datas'} -> [$problem_number-1] ->
3051 min
( column
=> $column_number );
3053 $min = $self -> {'problems'} -> [$problem_number-1] -> extra_data
->
3054 min
( column
=> $extra_data_column );
3069 my $fractions = $model_object -> fractions;
3085 =item problem_number
3089 =item return_occurences
3093 =item ignore_missing
3101 fractions will return the fractions from data::fractions. It will find
3102 "column_head" in the $INPUT record instead of that data header as
3103 data::fractions does.
3111 # @name_val = @{$modobj -> name_val( parameter_type => 'theta' )};
3113 # This basic usage takes one arguments and returns matched names and
3114 # estimated values of the specified parameter. The parameter_type argument
3116 # The names are taken from
3117 # the labels of the parameters (se the labels method for specifications of
3118 # default labels) and the values are aquired from the output object bound
3119 # to the model object. If no output exists, the name_val method returns
3121 # @name_val will be a two-dimensional array of references to hashes using
3122 # the names from each problem as keys:
3123 # [[ref to hash1 ][ref to hash2][ref to hash3]...]
3125 # $modobj -> name_val( parameter_type => 'theta',
3126 # problem_numbers => [2,4] );
3128 # To get matched names and values of specific problems, the problem_numbers argument
3129 # can be used. It should be a reference to an array containing the numbers
3130 # of all problems whos names and values should be retrieved.
3132 # $modobj -> name_val( parameter_type => 'theta',
3133 # problem_numbers => [2,4],
3134 # parameter_numbers => [[1,3][4,6]]);
3136 # The retrieval can be even more specific by using the parameter_numbers
3137 # argument. It should be a reference to a two-dimensional array, where
3138 # the inner arrays holds the numbers of the parameters that should be
3139 # fetched. In the example above, parameters one and three from problem two
3140 # plus parameters four and six from problem four are retrieved.
3143 unless( $#problem_numbers > 0 ){
3144 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
3146 my @names = @
{$self -> labels
( parameter_type
=> $parameter_type,
3147 parameter_numbers
=> \
@parameter_numbers,
3148 problem_numbers
=> \
@problem_numbers )};
3150 if ( defined $self -> outputs
-> [0] ) {
3151 my $accessor = $parameter_type.'s';
3152 @values = @
{$self -> outputs
-> [0] ->
3153 $accessor( problems
=> \
@problem_numbers,
3154 parameter_numbers
=> \
@parameter_numbers )};
3155 # my @problems = @{$self -> {'problems'}};
3156 # foreach my $i ( @problem_numbers ) {
3157 # if ( defined $problems[ $i-1 ] ) {
3158 # my $pn_ref = $#parameter_numbers >= 0 ? \@{$parameter_numbers[ $i-1 ]} : [];
3159 # push( @names_values,
3160 # $problems[ $i-1 ] ->
3161 # name_val( parameter_type => $parameter_type,
3162 # parameter_numbers => $pn_ref ) );
3164 # die "Model -> name_val: Problem number $i does not exist!\n";
3168 # if ( scalar @{$self -> {'outputs'}} > 0 ) {
3169 # my $outobj = $self -> {'outputs'} -> [0];
3172 'debug' -> die( message
=> "The number of problems retrieved from the model" .
3173 " do not match the ones retrived from the output" ) unless( $#names == $#values );
3174 for( my $i = 0; $i <= $#names; $i++ ) {
3175 'debug' -> die( message
=> "Problem " . $i+1 .
3176 " The number of parameters retrieved from the model (".scalar @
{$names[$i]}.
3177 ") do not match the ones retrived from the output (".
3178 scalar @
{$values[$i][0]}.")" )
3179 unless( scalar @
{$names[$i]} == scalar @
{$values[$i][0]} );
3181 for( my $j = 0; $j < scalar @
{$values[$i]}; $j++ ){
3183 for( my $k = 0; $k < scalar @
{$names[$i]}; $k++ ){
3184 $nv{$names[$i][$k]} = $values[$i][$j][$k];
3186 push( @prob_nv, \
%nv );
3188 push( @names_values, \
@prob_nv );
3203 my $fractions = $model_object -> fractions;
3219 =item problem_number
3223 =item return_occurences
3227 =item ignore_missing
3235 fractions will return the fractions from data::fractions. It will find
3236 "column_head" in the $INPUT record instead of that data header as
3237 data::fractions does.
3243 # nproblems returns the number of problems in the modelobject.
3245 $number_of_problem = scalar @
{$self -> {'problems'}};
3259 my $fractions = $model_object -> fractions;
3275 =item problem_number
3279 =item return_occurences
3283 =item ignore_missing
3291 fractions will return the fractions from data::fractions. It will find
3292 "column_head" in the $INPUT record instead of that data header as
3293 data::fractions does.
3299 # returns the number of thetas in the model for the given
3301 $nthetas = $self -> _parameter_count
( 'record' => 'theta', 'problem_number' => $problem_number );
3315 my $fractions = $model_object -> fractions;
3331 =item problem_number
3335 =item return_occurences
3339 =item ignore_missing
3347 fractions will return the fractions from data::fractions. It will find
3348 "column_head" in the $INPUT record instead of that data header as
3349 data::fractions does.
3355 # returns the number of omegas in the model for the given
3357 # $nomegas = $self -> _parameter_count( 'record' => 'omega', 'problem_number' => $problem_number );
3358 unless( $#problem_numbers >= 0 ){
3359 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
3362 my @problems = @
{$self -> {'problems'}};
3363 foreach my $i ( @problem_numbers ) {
3364 if ( defined $problems[ $i-1 ] ) {
3365 push( @nomegas, $problems[ $i-1 ] -> nomegas
( with_correlations
=> $with_correlations ));
3367 'debug' -> die( "Problem number $i does not exist." );
3383 my $fractions = $model_object -> fractions;
3399 =item problem_number
3403 =item return_occurences
3407 =item ignore_missing
3415 fractions will return the fractions from data::fractions. It will find
3416 "column_head" in the $INPUT record instead of that data header as
3417 data::fractions does.
3423 # returns the number of sigmas in the model for the given problem number.
3425 # $nsigmas = $self -> _parameter_count( 'record' => 'sigma', 'problem_number' => $problem_number );
3427 unless( $#problem_numbers >= 0 ){
3428 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
3431 my @problems = @
{$self -> {'problems'}};
3432 foreach my $i ( @problem_numbers ) {
3433 if ( defined $problems[ $i-1 ] ) {
3434 push( @nsigmas, $problems[ $i-1 ] -> nsigmas
( with_correlations
=> $with_correlations ));
3436 'debug' -> die( "Problem number $i does not exist." );
3452 my $fractions = $model_object -> fractions;
3468 =item problem_number
3472 =item return_occurences
3476 =item ignore_missing
3484 fractions will return the fractions from data::fractions. It will find
3485 "column_head" in the $INPUT record instead of that data header as
3486 data::fractions does.
3494 # This method is a (partially) automatically generated accessor for the
3495 # outputfile attribute of the model class. Since no named argument is needed
3496 # for accessors, the two possible ways of calling outputfile are:
3498 # $modelObject -> outputfile( 'newfilename.lst' );
3500 # $outputfilename = $modelObject -> outputfile;
3502 # The first alternative sets a new name for the output file, and the second
3503 # retrieves the value.
3505 # The extra feature for this accessor, compared to other accessors, is that
3506 # if a new name is given, the accessor tries to create a new output object
3509 if( defined $parm ) {
3510 $self -> {'outputs'} =
3512 new
( filename
=> $parm,
3513 ignore_missing_files
=> ( $self -> ignore_missing_files
() || $self -> ignore_missing_output_files
() ),
3514 target
=> $self -> target
(),
3515 model_id
=> $self -> model_id
() ) ];
3530 my $fractions = $model_object -> fractions;
3546 =item problem_number
3550 =item return_occurences
3554 =item ignore_missing
3562 fractions will return the fractions from data::fractions. It will find
3563 "column_head" in the $INPUT record instead of that data header as
3564 data::fractions does.
3570 # sets or gets the pk code for a given problem in the
3571 # model object. The new_pk argument should be an array where
3572 # each element contains a row of a valid NONMEM $PK block,
3574 my @prob = @
{$self -> problems
};
3576 unless( defined $prob[$problem_number - 1] ){
3577 'debug' -> die( message
=> "Problem number $problem_number does not exist" );
3580 my $pks = $prob[$problem_number - 1] -> pks
;
3581 if( scalar @new_pk > 0 ) {
3582 if( defined $pks and scalar @
{$pks} > 0 ){
3583 $prob[$problem_number - 1] -> pks
-> [0] -> code
(\
@new_pk);
3585 'debug' -> die( message
=> "No \$PK record" );
3588 if ( defined $pks and scalar @
{$pks} > 0 ) {
3589 @pk = @
{$prob[$problem_number - 1] -> pks
-> [0] -> code
};
3605 my $fractions = $model_object -> fractions;
3621 =item problem_number
3625 =item return_occurences
3629 =item ignore_missing
3637 fractions will return the fractions from data::fractions. It will find
3638 "column_head" in the $INPUT record instead of that data header as
3639 data::fractions does.
3645 # Sets or gets the pred code for a given problem in the model
3646 # object. See L</pk> for details.
3647 my @prob = @
{$self -> problems
};
3649 unless( defined $prob[$problem_number - 1] ){
3650 'debug' -> die( message
=> "problem number $problem_number does not exist" );
3653 if( scalar @new_pred > 0 ) {
3654 if( defined $prob[$problem_number - 1] -> preds
){
3655 $prob[$problem_number - 1] -> preds
-> [0] -> code
(\
@new_pred);
3657 'debug' -> die( message
=> "No \$PRED record" );
3660 if ( defined $prob[$problem_number - 1] -> preds
) {
3661 @pred = @
{$prob[$problem_number - 1] -> preds
-> [0] -> code
};
3663 'debug' -> die( message
=> "No \$PRED record" );
3679 my $fractions = $model_object -> fractions;
3695 =item problem_number
3699 =item return_occurences
3703 =item ignore_missing
3711 fractions will return the fractions from data::fractions. It will find
3712 "column_head" in the $INPUT record instead of that data header as
3713 data::fractions does.
3719 # Prints the formatted model to standard out.
3722 foreach my $problem ( @
{$self -> {'problems'}} ) {
3723 push( @formatted, $problem -> format_problem
);
3725 for ( @formatted ) {
3733 # {{{ problem_structure
3735 start problem_structure
3737 my ( $val, $pos ) = $self -> _option_val_pos
( record_name
=> 'simulation',
3738 name
=> 'SUBPROBLEMS' );
3739 if( defined $val ) {
3741 for( my $i = 0; $i <= $#vals; $i++ ) {
3742 if( defined $vals[$i] ) {
3743 if( scalar @
{$vals[$i]} > 0 ) {
3744 $subproblems[$i] = $vals[$i][0];
3746 $subproblems[$i] = 1;
3749 $subproblems[$i] = 1;
3754 end problem_structure
3756 # }}} problem_structure
3758 # {{{ randomize_inits
3766 my $fractions = $model_object -> fractions;
3782 =item problem_number
3786 =item return_occurences
3790 =item ignore_missing
3798 fractions will return the fractions from data::fractions. It will find
3799 "column_head" in the $INPUT record instead of that data header as
3800 data::fractions does.
3804 start randomize_inits
3806 foreach my $prob ( @
{$self -> {'problems'}} ) {
3807 $prob -> set_random_inits
( degree
=> $degree );
3823 my $fractions = $model_object -> fractions;
3839 =item problem_number
3843 =item return_occurences
3847 =item ignore_missing
3855 fractions will return the fractions from data::fractions. It will find
3856 "column_head" in the $INPUT record instead of that data header as
3857 data::fractions does.
3863 # If the argument new_data is given, record sets new_data in
3864 # the model objects member specified with record_name. The
3865 # format of new_data is an array of strings, where each
3866 # element corresponds to a line of code as it would have
3867 # looked like in a valid NONMEM modelfile. If new_data is left
3868 # undefined, record returns lines of code belonging to the
3869 # record specified by record_name in a format that is valid in
3870 # a NONMEM modelfile.
3872 my @problems = @
{$self -> {'problems'}};
3875 if ( defined $problems[ $problem_number - 1 ] ) {
3876 if ( scalar(@new_data) > 0 ){
3877 my $rec_class = "model::problem::$record_name";
3878 my $record = $rec_class -> new
('record_arr' => \
@new_data );
3880 $record_name .= 's';
3881 $records = $problems[ $problem_number - 1 ] -> {$record_name};
3882 foreach my $record( @
{$records} ){
3883 push(@data, $record -> _format_record
);
3900 my $fractions = $model_object -> fractions;
3916 =item problem_number
3920 =item return_occurences
3924 =item ignore_missing
3932 fractions will return the fractions from data::fractions. It will find
3933 "column_head" in the $INPUT record instead of that data header as
3934 data::fractions does.
3942 # $model -> remove_inits( type => 'theta',
3943 # indexes => [1,2,5,6] )
3946 # In all cases the type must be set to theta. Removing Omegas in
3947 # Sigmas is not allowed, (If need that feature, send us a
3948 # mail). In the above example the thetas 1, 2, 5 and 6 will be
3949 # removed from the modelfile. Notice that this alters the theta
3950 # numbering, so if you later decide that theta number 7 must be
3951 # removed as well, you must calculate its new position in the
3952 # file. In this case the new number would be 3. Also notice that
3953 # numbering starts with 1.
3955 # $model -> remove_inits( type => 'theta',
3956 # labels => ['V', 'CL'] )
3959 # If you have specified labels in you modelfiles(a label is
3960 # string inside a comment on the same row as the theta) you can
3961 # specify an array with labels, and the corresponding theta, if
3962 # it exists, will be removed. This is a much better approach
3963 # since you don't need to know where in order the theta you wish
3964 # to remove appears. If you specify both labels and indexes, the
3965 # indexes will be ignored.
3967 'debug' -> die( message
=> 'does not have the functionality for removing $OMEGA or $SIGMA options yet' )
3968 if ( $type eq 'omega' or $type eq 'sigma' );
3969 my $accessor = $type.'s';
3971 # First pick out a referens to the theta records array.
3972 my $inits_ref = $self -> problems
-> [$problem_number -1] -> $accessor;
3974 # If we have any thetas at all:
3975 if ( defined $inits_ref ) {
3976 my @inits = @
{$inits_ref};
3978 # If labels are specified, we translate the labels into
3980 if ( scalar @labels > 0 ) {
3983 # Loop over theta records
3984 foreach my $init ( @inits ) {
3985 # Loop over the individual thetas inside
3986 foreach my $option ( @
{$init -> options
} ) {
3987 # Loop over all given labels.
3988 foreach my $label ( @labels ) {
3989 # Push the index number if a given label match the
3991 push( @indexes, $i ) if ( $option -> label
eq $label);
3993 # $i is the count of thetas so far
3999 # We don't really remove thetas, we do a loop over all thetas
4000 # and recording which we like to keep. We do that by selecting
4001 # an index, from @indexes, that shall be removed and loop over
4002 # the thetas, all thetas that doesn't match the index are
4003 # stored in @keep_options. When we find a theta that matches,
4004 # we pick a new index and continue the loop. So by makeing
4005 # sure that @indexes is sorted, we only need to loop over the
4008 @indexes = sort {$a <=> $b} @indexes;
4014 # Loop over all records
4015 RECORD_LOOP
: foreach my $record ( @inits ){
4016 my @keep_options = ();
4017 # Loop over all thetas
4018 foreach my $option ( @
{$record -> options
} ) {
4019 if( $indexes[ $index ] == $nr_options ){
4020 # If a theta matches an index, we take the next index
4021 # and forget the theta.
4022 unless( $index > $#indexes ){
4026 # Otherwise we rember it.
4027 push(@keep_options,$option);
4031 if( scalar(@keep_options) > 0 ){
4032 # If we remember some thetas, we must also remember the
4033 # record which they are in.
4034 $record -> options
( \
@keep_options );
4035 push( @keep_records, $record );
4039 # Set the all kept thetas back into the modelobject.
4040 @
{$inits_ref} = @keep_records;
4043 'debug' -> die( message
=> "No init of type $type defined" );
4058 my $fractions = $model_object -> fractions;
4074 =item problem_number
4078 =item return_occurences
4082 =item ignore_missing
4090 fractions will return the fractions from data::fractions. It will find
4091 "column_head" in the $INPUT record instead of that data header as
4092 data::fractions does.
4098 # restore_inits brings back initial values previously stored
4099 # using store_inits. This method pair allows a user to store
4100 # the currents initial values in a backup, replace them with
4101 # temporary values and later restore them.
4103 if ( defined $self -> {'problems'} ) {
4104 foreach my $problem ( @
{$self -> {'problems'}} ){
4105 $problem -> restore_inits
;
4121 my $fractions = $model_object -> fractions;
4137 =item problem_number
4141 =item return_occurences
4145 =item ignore_missing
4153 fractions will return the fractions from data::fractions. It will find
4154 "column_head" in the $INPUT record instead of that data header as
4155 data::fractions does.
4161 # store_inits stores initial values that can later be
4162 # brought back using restore_inits. See L</restore_inits>.
4164 if ( defined $self -> {'problems'} ) {
4165 foreach my $problem ( @
{$self -> {'problems'}} ){
4166 $problem -> store_inits
;
4178 # Synchronize checks the I<synced> object attribute to see
4179 # if the model is in sync with its corresponding file, given
4180 # by the objetc attribute I<filename>. If not, it checks if
4181 # the model contains any defined problems and if it does, it
4182 # writes the formatted model to disk, overwriting any
4183 # existing file of name I<filename>. If no problem is
4184 # defined, synchronize tries to parse the file I<filename>
4185 # and set the object internals to match it.
4186 unless( $self -> {'synced'} ){
4187 if( defined $self -> {'problems'} and
4188 scalar @
{$self -> {'problems'}} > 0 ){
4191 if( -e
$self -> full_name
){
4192 $self -> _read_problems
;
4198 $self -> {'synced'} = 1;
4206 # synchronizes the object with the file on disk and empties
4207 # most of the objects attributes to save memory.
4208 if( defined $self -> {'problems'} and
4209 ( !$self -> {'synced'} or $force ) ) {
4212 $self -> {'problems'} = undef;
4213 $self -> {'synced'} = 0;
4221 if ( $parm eq 'disk' ) {
4222 $self -> {'target'} = 'disk';
4224 } elsif ( $parm eq 'mem' and $self -> {'target'} eq 'disk' ) {
4225 $self -> {'target'} = 'mem';
4226 $self -> synchronize
;
4240 my $msfi_names_ref = $model_object -> msfi_names;
4252 =item problem_numbers
4256 =item ignore_missing_files
4264 msfi_names will return the names of all MSFI= statements in the
4265 $ESTIMATION records in all problems.
4272 # @msfiNames = @{$modobj -> msfi_names};
4276 # $msfiNamesRef = $modobj -> msfi_names;
4277 # @msfiNames = @{$msfiNamesRef} if (defined $msfiNamesRef);
4279 # This basic usage takes no arguments and returns the value of
4280 # the MSFI option in the $ESTIMATION NONMEM record of each
4281 # problem. @msfiNames will be a two-dimensional array:
4283 # [[msfiName_prob1],[msfiName_prob2],[msfiName_prob3]...]
4287 if ( defined $self -> problems
() ) {
4288 @problems = @
{$self -> problems
()};
4290 'debug' -> die( message
=> "No problems defined in model" );
4293 if( scalar @new_names > 0 ) {
4295 foreach my $prob ( @problems ) {
4296 $prob -> remove_records
( type
=> 'msfi' );
4297 if( defined $new_names[$i] ) {
4298 $prob -> add_records
( type
=> 'msfi',
4299 record_strings
=> [$new_names[$i]] );
4303 foreach my $prob ( @problems ) {
4304 if ( defined $prob -> msfis
() ) {
4305 my @instances = @
{$prob -> msfis
()};
4307 foreach my $instance ( @instances ) {
4309 if ( defined $instance -> options
() ) {
4310 @options = @
{$instance -> options
()};
4312 if ( defined $options[0] ) {
4313 push( @prob_names, $options[0] -> name
);
4315 push( @prob_names, undef );
4318 push( @names, \
@prob_names );
4320 push( @names, undef );
4337 my $msfo_names_ref = $model_object -> msfo_names;
4349 =item problem_numbers
4353 =item ignore_missing_files
4361 msfo_names will return the names of all MSFO= statements in the
4362 $ESTIMATION records in all problems.
4369 # @msfoNames = @{$modobj -> msfo_names};
4373 # $msfoNamesRef = $modobj -> msfo_names;
4374 # @msfoNames = @{$msfoNamesRef} if (defined $msfoNamesRef);
4376 # This basic usage takes no arguments and returns the value of
4377 # the MSFO option in the $ESTIMATION NONMEM record of each
4378 # problem. @msfoNames will be an array:
4380 # [msfoName_prob1,msfoName_prob2,msfoName_prob3...]
4383 # If the I<new_names> argument of msfo_names is given, the
4384 # values of the MSFO options will be changed.
4386 # To set the MSFO of specific problems, the I<problem_numbers>
4387 # argument can be used. It should be a reference to an array
4388 # containing the numbers of all problems where the FILE should
4389 # be changed or retrieved. If specified, the size of
4390 # I<new_names> must be the same as the size of
4391 # I<problem_numbers>.
4393 my ( $name_ref, $junk ) = $self ->
4394 _option_val_pos
( name
=> 'MSFO',
4395 record_name
=> 'estimation',
4396 problem_numbers
=> \
@problem_numbers,
4397 new_values
=> \
@new_names );
4400 my ( $nonp_name_ref, $junk ) = $self ->
4401 _option_val_pos
( name
=> 'MSFO',
4402 record_name
=> 'nonparametric',
4403 problem_numbers
=> \
@problem_numbers,
4404 new_values
=> \
@new_names );
4406 if( length( @
{$name_ref} > 0 ) ){
4407 push( @names, @
{$name_ref} );
4410 if( length( @
{$nonp_name_ref} ) ){
4411 push( @names, @
{$nonp_name_ref} );
4426 my $fractions = $model_object -> fractions;
4442 =item problem_number
4446 =item return_occurences
4450 =item ignore_missing
4458 fractions will return the fractions from data::fractions. It will find
4459 "column_head" in the $INPUT record instead of that data header as
4460 data::fractions does.
4468 # @tableNames = @{$modobj -> table_names};
4470 # This basic usage takes no arguments and returns the value of
4471 # the FILE option in the $TABLE NONMEM record of each
4472 # problem. @tableNames will be a two dimensional array:
4474 # [[tableName_prob1][tableName_prob2][tableName_prob3]...]
4477 # If the I<new_names> argument of table_names is given, the
4478 # values of the FILE options will be changed.
4480 # To set the FILE of specific problems, the I<problem_numbers>
4481 # argument can be used. It should be a reference to an array
4482 # containing the numbers of all problems where the FILE should
4483 # be changed or retrieved. If specified, the size of
4484 # I<new_names> must be the same as the size of
4485 # I<problem_numbers>.
4487 # The I<ignore_missing_files> boolean argument can be used to
4488 # set names of table that does not exist yet (e.g. before a
4489 # run has been performed).
4491 my ( $name_ref, $junk ) = $self ->
4492 _option_val_pos
( name
=> 'FILE',
4493 record_name
=> 'table',
4494 problem_numbers
=> \
@problem_numbers,
4495 new_values
=> \
@new_names );
4496 if ( $#new_names >= 0 ) {
4497 my @problems = @
{$self -> {'problems'}};
4498 unless( $#problem_numbers > 0 ){
4499 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
4501 foreach my $i ( @problem_numbers ) {
4502 $problems[$i-1] -> _read_table_files
( ignore_missing_files
=> $ignore_missing_files || $self -> {'ignore_missing_output_files'});
4505 @names = @
{$name_ref};
4519 my $fractions = $model_object -> fractions;
4535 =item problem_number
4539 =item return_occurences
4543 =item ignore_missing
4551 fractions will return the fractions from data::fractions. It will find
4552 "column_head" in the $INPUT record instead of that data header as
4553 data::fractions does.
4561 # @table_files = @{$modobj -> table_files};
4563 # This basic usage takes no arguments and returns the table
4564 # files objects for all problems. @table_files will be a
4565 # two dimensional array:
4567 # [[table_file_object_prob1][table_file_object_prob2]...]
4570 # To retrieve the table file objects from specific problems,
4571 # the I<problem_numbers> argument can be used. It should be
4572 # a reference to an array containing the numbers of all
4573 # problems from which the table file objects should be
4576 unless( $#problem_numbers > 0 ){
4577 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
4579 my @problems = @
{$self -> {'problems'}};
4580 foreach my $i ( @problem_numbers ) {
4581 if ( defined $problems[ $i-1 ] ) {
4582 push( @table_files, $problems[$i-1] -> table_files
);
4584 'debug' -> die( message
=> "Problem number $i does not exist!" );
4600 my $fractions = $model_object -> fractions;
4616 =item problem_number
4620 =item return_occurences
4624 =item ignore_missing
4632 fractions will return the fractions from data::fractions. It will find
4633 "column_head" in the $INPUT record instead of that data header as
4634 data::fractions does.
4640 # Sets or gets the units of a (number of) parameter(s). The
4641 # unit is not a proper NONMEM syntax but is recognized by
4642 # the PsN model class. A unit (and a label) can be specified
4643 # as a comments after a parameter definition. e.g.:
4645 # $THETA (0,13.2,100) ; MTT; h
4647 # which will give this theta the label I<MTT> and unit I<h>.
4648 @units = @
{ $self -> _init_attr
( parameter_type
=> $parameter_type,
4649 parameter_numbers
=> \
@parameter_numbers,
4650 problem_numbers
=> \
@problem_numbers,
4651 new_values
=> \
@new_values,
4667 my $fractions = $model_object -> fractions;
4683 =item problem_number
4687 =item return_occurences
4691 =item ignore_missing
4699 fractions will return the fractions from data::fractions. It will find
4700 "column_head" in the $INPUT record instead of that data header as
4701 data::fractions does.
4709 # $modobj -> update_inits ( from_output => $outobj );
4713 # $modobj -> update_inits ( from_output_file => $outfile );
4715 # This basic usage takes the parameter estimates from the
4716 # output object I<$outobj> or from the output file I<$outfile>
4717 # and updates the initial estimates in the model object
4718 # I<$modobj>. The number of problems and parameters must be
4719 # the same in the model and output objects. If there exist
4720 # more than one subproblem per problem in the output object,
4721 # only the estimates from the first subproblem will be
4724 # $modobj -> update_inits ( from_output => $outobj,
4725 # ignore_missing_parameters => 1 );
4727 # If the ignore_missing_parameters argument is set to 1, the number of
4728 # parameters in the model and output objects do not need to match. The
4729 # parameters that exist in both objects are used for the update of the
4732 # $modobj -> update_inits ( from_output => $outobj,
4733 # from_model => $from_modobj );
4735 # If the from_model argument is given, update_inits tries to match the
4736 # parameter names (labels) given in $from_modobj and $modobj and
4737 # and thereafter updating the $modobj object. See L</units> and L</labels>.
4740 my ( %labels, @own_labels, @from_labels );
4741 'debug' -> die( message
=> "No output object defined and" .
4742 " no output object found through the model object specified." )
4743 unless ( ( defined $from_model and
4744 ( defined $from_model -> outputs
and
4745 defined @
{$from_model -> outputs
}[0] ) ) or
4746 defined $from_output or
4747 defined $from_output_file );
4748 if ( defined $from_output ) {
4749 'debug' -> warn( level
=> 2,
4750 message
=> "using output object ".
4751 "specified as argument\n" );
4752 } elsif ( defined $from_output_file ) {
4753 $from_output = output
-> new
( filename
=> $from_output_file );
4755 $from_output = @
{$from_model -> outputs
}[0];
4759 if( $update_thetas ){
4760 push( @params, 'theta' );
4762 if( $update_omegas ) {
4763 push( @params, 'omega' );
4765 if( $update_sigmas ) {
4766 push( @params, 'sigma' );
4769 foreach my $param ( @params ) {
4770 # Get own labels and from labels
4771 if ( defined $from_model ) {
4772 @own_labels = @
{$self -> labels
( parameter_type
=> $param )};
4774 @from_labels = @
{$from_model -> labels
( parameter_type
=> $param )};
4775 'debug' -> die( message
=> "The number of problems are not the same in from-model ".
4776 $from_model -> full_name
." (".
4777 ($#from_labels+1).")".
4778 " and the model to be updated ".
4779 $self -> full_name
." (".
4780 ($#own_labels+1).")" ) unless ( $#own_labels == $#from_labels );
4782 @own_labels = @
{$self -> labels
( parameter_type
=> $param,
4784 @from_labels = @
{$from_output -> labels
( parameter_type
=> $param )};
4785 'debug' -> die( message
=> "The number of problems are not the same in from-output ".
4786 $from_output -> full_name
." (".
4787 ($#from_labels+1).")".
4788 " and the model to be updated ".
4789 $self -> full_name
." (".
4790 ($#own_labels+1).")" ) unless ( $#own_labels == $#from_labels );
4793 # Loop over the problems:
4794 my $accessor = $param.'s';
4795 # Since initial estimates are specified on the problem level and not on
4796 # the subproblem level we use the estimates from the outputs first subproblem
4797 my @from_values = @
{$from_output -> $accessor ( subproblems
=> [1] )};
4798 # {{{ Omega and Sigma update section
4800 # The functionality that has been commented out because it
4801 # fails when omegas are zero. This functionality should be
4802 # moved to output::problem::subproblem (2005-02-09) TODO
4804 # if ($param eq 'omega' or $param eq 'sigma')
4806 # #print "FL: ", Dumper @from_labels;
4807 # #print "OL: ", Dumper @own_labels;
4808 # print "FV: $param Before " . Dumper(@from_values) . "\n";
4809 # #Fix omegas and sigmas so that the correlation between elements <=1
4810 # my $raw_accessor = "raw_" . $accessor;
4811 # my @raw_from_values = @{$from_output -> $raw_accessor(subproblems => [1])};
4813 # for (my $a=0; $a<scalar(@from_values); $a++)
4815 # my $prob_values = $from_values[$a];
4816 # my $raw_prob_values = $raw_from_values[$a];
4817 # for (my $b=0; $b<scalar(@{$prob_values}); $b++)
4819 # my $values = $prob_values->[$b];
4820 # my $raw_values = $raw_prob_values->[$b];
4822 # #Find out the n*n-matrix size (pq-formula)
4823 # my $n = int(sqrt(1/4+scalar(@{$raw_values})*2)-1/2);
4824 # for ($i=0; $i<$n; $i++)
4826 # for ($j=0; $j<$n; $j++)
4828 # if ( $j<=$i && $raw_values->[$i*($i+1)/2+$j]!=0 )
4830 # #print "Omega value = " . @other_val[$counter] . "\n";
4833 # #Only check the low-triangular off-diagonals of the omega matrix
4834 # #omega(i,j)>=sqrt(omega(i,i)*omega(j,j))
4835 # if ($j<=$i && $j!=$i &&
4836 # ($raw_values->[$i*($i+1)/2+$j]>=sqrt(
4837 # $raw_values->[$i*($i+1)/2+$i]*$raw_values->[$j*($j+1)/2+$j])))
4839 # print "Changing raw value at $i, $j: " . $raw_values->[$i*($i+1)/2+$j] ." to ".
4840 # (int(10000*sqrt($raw_values->[$i*($i+1)/2+$i]*$raw_values->[$j*($j+1)/2+$j]))/10000) ."\n";
4841 # #print "At index ($i,$j)\n" if ($self->{'debug'});
4842 # $raw_values->[$i*($i+1)/2+$j]=int(10000*sqrt(
4843 # $raw_values->[$i*($i+1)/2+$i]*$raw_values->[$j*($j+1)/2+$j]))/10000;
4844 # print "Changing omega value " . $values->[$counter-1] . " to " . $raw_values->[$i*($i+1)/2+$j] ."\n";
4845 # $values->[$counter-1] = $raw_values->[$i*($i+1)/2+$j];
4851 # #print "FL: ", Dumper @from_labels;
4852 # #print "OL: ", Dumper @own_labels;
4853 # print "FV: $param After ", Dumper(@from_values), "\n";
4859 for ( my $i = 0; $i <= $#own_labels; $i++ ) {
4861 if( $from_output -> have_user_defined_prior
){
4862 $ignore_missing_parameters = 1;
4864 unless ( $ignore_missing_parameters ) {
4865 my $from_name = defined $from_model ?
$from_model -> filename
:
4866 $from_output -> filename
;
4867 'debug' -> die( message
=> "Model -> update_inits: The number of ".$param.
4868 "s are not the same in from-model (" . $from_name .
4869 "): " . scalar @
{$from_labels[$i]} .
4870 ", and the model to be updated (" . $self -> {'filename'} .
4871 "): " . scalar @
{$own_labels[$i]} )
4872 unless ( scalar @
{$own_labels[$i]} ==
4873 scalar @
{$from_labels[$i]} );
4876 for ( my $j = 0; $j < scalar @
{$from_labels[$i]}; $j++ ) {
4877 for ( my $k = 0; $k < scalar @
{$own_labels[$i]}; $k++ ) {
4878 if ( $from_labels[$i][$j] eq $own_labels[$i][$k] ){
4879 $labels{$k+1} = $from_values[$i][0][$j];
4884 my @own_idxs = keys( %labels );
4886 for(my $i=0; $i <= $#own_idxs; $i++){
4887 @from_vals[$i] = $labels{ $own_idxs[$i] };
4890 $self -> initial_values
( problem_numbers
=> [$i+1],
4891 parameter_type
=> $param,
4892 parameter_numbers
=> [\
@own_idxs],
4893 new_values
=> [\
@from_vals] );
4905 # upper_bounds either sets or gets the initial values of the
4906 # parameter specified in I<parameter_type> for each
4907 # subproblem specified in I<problem_numbers>. For each
4908 # element in I<problem_numbers> there must be an array in
4909 # I<parameter_numbers> that specify the indices of the
4910 # parameters in the subproblem for which the upper bounds
4911 # are set, replaced or retrieved.
4913 @upper_bounds = @
{ $self -> _init_attr
4914 ( parameter_type
=> $parameter_type,
4915 parameter_numbers
=> \
@parameter_numbers,
4916 problem_numbers
=> \
@problem_numbers,
4917 new_values
=> \
@new_values,
4918 attribute
=> 'upbnd')};
4924 # {{{ clean_extra_data_code
4925 start clean_extra_data_code
4928 # This method cleans out old code for extra data. It searches
4929 # all subroutine statements in all problems for external
4930 # subroutines named "get_sub" and "reader" which are added by
4931 # "add_extra_data_code".
4933 foreach my $problem( @
{$self -> {'problems'}} ){
4934 if ( defined $problem -> subroutines
and defined $problem -> subroutines
-> [0] -> options
) {
4935 foreach my $option ( @
{$problem -> subroutines
-> [0] -> options
} ){
4936 if( lc($option -> name
) eq 'other'){
4937 if( lc($option -> value
) =~ /get_sub|reader/ ){
4939 # If we find "get_sub" or "reader" we remove
4940 # everything between "IMPORTING COVARIATE DATA" and
4941 # "IMPORTING COVARIATE DATA END" by finding the
4942 # indexes in the code array and and splicing it out.
4945 if( $problem -> pks
){
4946 # If the code is in a pk block:
4947 $code = $problem -> pks
-> [0] -> code
;
4949 $code = $problem -> preds
-> [0] -> code
;
4954 for( my $i = 0; $i <= $#{$code}; $i++ ){
4955 if( $code -> [$i] eq ";***IMPORTING COVARIATE DATA*******\n" ){
4958 if( $code -> [$i] eq ";***IMPORTING COVARIATE DATA END***\n" ){
4962 @
{$code} = ( @
{$code}[0..$start_idx] , @
{$code}[$end_idx..$#{$code}] );
4964 if( $problem -> pks
){
4965 # Put the cut down code back in the right place:
4966 $problem -> pks
-> [0] -> code
( $code );
4968 $problem -> preds
-> [0] -> code
( $code );
4978 end clean_extra_data_code
4979 # }}} clean_extra_data_code
4981 # {{{ add_extra_data_code
4983 start add_extra_data_code
4985 # This method adds fortran code that will handle wide datasets
4986 # (that is data sets with more than 20 columns). It adds code to
4987 # each problems pk or pred.
4991 # Get the headers of the columns that have been moved to another
4994 # unless( defined $self -> extra_data_headers ){
4995 # die "ERROR model::add_extra_data_code: No headers for the extra data file\n";
4998 # extra_data_headers is a two dimensional array. One array of
4999 # headers for each problem in the modelfile.
5000 for( my $i = 0; $i <= $#{$self -> {'problems'}}; $i++ ){
5001 if ( defined $self -> {'problems'} -> [$i] -> {'extra_data_header'} ) {
5002 my $problem_headers = $self -> {'problems'} -> [$i] -> {'extra_data_header'};
5007 # Loop over the problem specific headers and make a string
5008 # that will go into the fortran code. Assume that the
5009 # first column holds the ID, hence the $i=1
5010 for (my $i = 1; $i <= $#{$problem_headers}; $i++ ) {
5011 my $header = $problem_headers -> [$i];
5012 push( @headers, $header );
5013 # Chopp the string at 40 characters, to be nice to g77 :)
5014 if ( $length + length($header) > 40 ) {
5015 $header_string .= "\n\"& ";
5018 if ( $i < $#{$problem_headers} ) {
5019 $header_string .= 'I' . $header . ', ';
5020 $length += length( 'I' . $header . ', ' );
5022 $header_string .= 'I' . $header;
5023 $length += length( 'I' . $header );
5027 my @code_lines = ('',
5028 ';***IMPORTING COVARIATE DATA*******',
5030 '" REAL CURID, MID,',
5031 '"& '.$header_string,
5034 '" IF (.NOT.READ) THEN',
5040 '" IF (NEWIND.LT.2) THEN',
5041 '" CALL GET_SUB (NEWIND,ID,CURID,MID,',
5042 '"& '.$header_string. ')',
5045 ' IF (CID.NE.ID) THEN',
5046 ' PRINT *, \'ERROR CHECKING FAILED, CID = \', CID ,\' ID = \', ID',
5050 foreach my $header ( @headers ) {
5051 push( @code_lines, " $header = I$header" );
5054 push( @code_lines, (';***IMPORTING COVARIATE DATA END***','','') );
5056 my $problem = $self -> {'problems'} -> [$i];
5057 if ( defined $problem -> {'subroutines'} ) {
5058 $problem -> subroutines
-> [0] -> _add_option
( option_string
=> 'OTHER=get_sub' . $i );
5059 $problem -> subroutines
-> [0] -> _add_option
( option_string
=> 'OTHER=reader' . $i );
5061 $problem -> add_records
( type
=> 'subroutines', record_strings
=> ['OTHER=get_sub', 'OTHER=reader'] );
5064 if ( defined $problem -> pks
) {
5065 unshift( @
{$problem -> pks
-> [0] -> code
}, join("\n", @code_lines ));
5067 unshift( @
{$problem -> preds
-> [0] -> code
},join("\n", @code_lines ));
5072 end add_extra_data_code
5080 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5081 $self -> {'datas'}[$i] -> drop_dropped
( model_header
=> $self -> {'problems'}[$i] -> header
);
5082 $self -> {'problems'}[$i] -> drop_dropped
( );
5083 #$self -> {'datas'}[$i] -> model_header( $self -> {'problems'}[$i] -> header );
5094 my $default_wrap = 18;
5096 $self -> drop_dropped
(1);
5098 my ( @wrap_columns, @cont_columns );
5099 if ( not defined $wrap_column ) {
5100 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5101 my $columns = scalar @
{$self -> {'problems'}[$i] -> dropped_columns
}-1; #skip ID
5102 my $modulus = $columns%($default_wrap-2); # default_wrap-2 to account for ID and CONT
5103 my $rows = (($columns-$modulus)/($default_wrap-2))+1;
5105 push( @wrap_columns, undef );
5107 push( @wrap_columns, (ceil
( $columns/$rows )+2) ); #Must use #cols + ID and CONT
5111 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5112 push( @wrap_columns, $wrap_column );
5116 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5117 next if ( not defined $wrap_columns[$i] );
5118 $wrap_column = $wrap_columns[$i];
5119 $cont_column = $wrap_columns[$i] if( not defined $cont_column );
5120 my ( $prim, $sec ) =
5121 $self -> {'datas'}[$i] -> wrap
( cont_column
=> $cont_column,
5122 wrap_column
=> $wrap_column,
5123 model_header
=> $self -> {'problems'}[$i] -> header
);
5124 $self -> {'problems'}[$i] -> primary_columns
( $prim );
5125 $self -> {'problems'}[$i] -> secondary_columns
( $sec );
5126 $self -> {'data_wrapped'}++;
5136 for( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5137 $self -> {'datas'}[$i] -> unwrap
;
5138 $self -> {'problems'}[$i] -> primary_columns
( [] );
5139 $self -> {'problems'}[$i] -> secondary_columns
( [] );
5141 $self -> {'data_wrapped'} = 0;
5146 # {{{ write_get_subs
5148 start write_get_subs
5150 for( my $i = 0; $i <= $#{$self -> {'problems'}}; $i++ ){
5151 if ( defined $self -> {'problems'} -> [$i] -> {'extra_data_header'} and
5152 defined $self -> problems
-> [$i] -> extra_data
) {
5153 my @problem_header = @
{$self -> {'problems'} -> [$i] -> {'extra_data_header'}};
5158 my $rows = $self -> problems
-> [$i] -> extra_data
-> count_ind
;
5160 # Assume that first column holds the ID. Get rid of it.
5161 shift( @problem_header );
5162 for ( my $i = 0; $i <= $#problem_header; $i++ ) {
5163 my $header = $problem_header[$i];
5164 push( @headers, $header );
5165 # Chop the string at 40 characters, to be nice to g77 :)
5166 if ( $length + length($header) > 40 ) {
5167 $header_string .= "\n & ";
5170 if ( $i < $#problem_header ) {
5171 $header_string .= $header . ', ';
5172 $length += length( $header . ', ' );
5174 $header_string .= $header;
5175 $length += length( $header );
5179 open( FILE
, '>', 'get_sub' . $i . '.f' );
5180 print FILE
(" SUBROUTINE GET_SUB (NEWIND,ID,CURID,MID,\n",
5181 " & $header_string)\n",
5182 " COMMON /READ/ TID,TCOV\n",
5184 " REAL ID,CURID,MID,\n",
5185 " & $header_string\n",
5187 " INTEGER NEWIND\n",
5189 " REAL TID($rows), TCOV($rows,",scalar @problem_header,")\n",
5192 "C START AT TOP EVERY TIME\n",
5193 " IF (NEWIND.EQ.1) THEN \n",
5195 " IF (CURID.GT.$rows) THEN \n",
5196 " PRINT *, \"Covariate data not found for\", ID\n",
5201 " IF (ID.GT.TID (CURID)) THEN\n",
5202 " CURID = CURID + 1\n",
5205 " ELSEIF (NEWIND.EQ.0) THEN\n",
5210 for ( my $i = 1; $i <= $#headers+1; $i++ ) {
5211 $length += length("TCOV(I,$i),");
5212 if ( $length > 40 ) {
5216 print FILE
" ".$headers[$i-1] . " = TCOV(CURID,$i)\n";
5219 print FILE
(" MID = TID(CURID)\n",
5236 for( my $i = 0; $i <= $#{$self -> {'problems'}}; $i++ ){
5237 if ( defined $self -> {'problems'} -> [$i] -> {'extra_data_header'} and
5238 defined $self -> {'problems'} -> [$i] -> {'extra_data'} ) {
5239 my @problem_header = @
{$self -> {'problems'} -> [$i] -> {'extra_data_header'}};
5243 my $rows = $self -> problems
-> [$i] -> extra_data
-> count_ind
;
5244 my $filename = $self -> problems
-> [$i] -> extra_data
-> filename
;
5245 # Assume that first column holds the ID. Get rid of it.
5246 shift( @problem_header );
5248 'debug' -> warn( level
=> 2,
5249 message
=> "Writing reader".$i.".f to directory".cwd
);
5250 open( FILE
, '>', 'reader' . $i . '.f' );
5251 print FILE
(" SUBROUTINE READER()\n",
5253 " COMMON /READ/ TID,TCOV\n",
5255 " REAL TID ($rows), TCOV ($rows, ",scalar @problem_header,")\n",
5257 " OPEN (UNIT = 77,FILE = '$filename')\n",
5259 " DO 11,I = 1,$rows\n",
5260 " READ (77,*) TID(I)," );
5263 for ( my $i = 1; $i <= $#problem_header+1; $i++ ) {
5264 $length += length("TCOV(I,$i),");
5265 if ( $length > 40 ) {
5269 if ( $i <= $#problem_header ) {
5270 print FILE
"TCOV(I,$i),";
5272 print FILE
"TCOV(I,$i)\n";
5276 print FILE
( "11 CONTINUE\n",
5290 # $model -> _write( filename => 'model.mod' );
5292 # Writes the content of the modelobject to disk. Either to the
5293 # filename given, or to the string returned by model::full_name.
5297 # An element in the active_problems array is a boolean that
5298 # corresponds to the element with the same index in the problems
5299 # array. If the boolean is true, the problem will be run. All
5300 # other will be commented out.
5301 my @active = @
{$self -> {'active_problems'}};
5303 # loop over all problems.
5304 for ( my $i = 0; $i < scalar @
{$self -> {'problems'}}; $i++ ) {
5305 # Call on the problem object to format it as text. The
5306 # filename and problem numbers are needed to make some
5307 # autogenerated files (msfi, tabels etc...) unique to the
5309 my @preformatted = @
{$self -> {'problems'} -> [$i] ->
5310 _format_problem
( filename
=> $self -> filename
,
5311 problem_number
=> ($i+1) ) };
5312 # Check if the problem is NOT active, if so comment it out.
5313 unless ( $active[$i] ) {
5314 for ( my $j = 0; $j <= $#preformatted; $j++ ) {
5315 $preformatted[$j] = '; '.$preformatted[$j];
5318 # Add extra line to avoid problems with execution of NONMEM
5319 push(@preformatted,"\n");
5320 push( @formatted, @preformatted );
5323 # Open a file and print the formatted problems.
5324 # TODO Add some errorchecking.
5325 open( FILE
, '>'. $filename );
5326 for ( @formatted ) {
5333 if ( $write_data ) {
5334 foreach my $data ( @
{$self -> {'datas'}} ) {
5339 if( $self -> {'iofv_modules'} ){
5340 $self -> {'iofv_modules'} -> [0] -> post_process
;
5351 if ( defined $parm and $parm ne $self -> {'filename'} ) {
5352 $self -> {'filename'} = $parm;
5353 $self -> {'model_id'} = undef;
5360 # {{{ _get_option_val_pos
5362 start _get_option_val_pos
5366 # ( $values_ref, $positions_ref ) ->
5367 # _get_option_val_pos ( name => 'ID',
5368 # record_name => 'input' );
5369 # my @values = @{$values_ref};
5370 # my @positions = @{$positions_ref};
5372 # This basic usage returns the name of the third option in the first
5373 # instance of the record specified by I<record_name> for all problems
5375 # If global_position is set to 1, only one value and position
5376 # pair is returned per problem. If there are more than one
5377 # match in the model; the first will be returned for each
5380 # Private method, should preferably not be used outside model.pm
5382 # my ( @records, @instances );
5383 my $accessor = $record_name.'s';
5384 my @problems = @
{$self -> {'problems'}};
5385 unless( $#problem_numbers > 0 ){
5386 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5388 foreach my $i ( @problem_numbers ) {
5389 my $rec_ref = $problems[ $i-1 ] -> $accessor;
5390 if ( defined $problems[ $i-1 ] and defined $rec_ref ) {
5391 my @records = @
{$rec_ref};
5392 unless( $#instances > 0 ){
5393 @instances = (1 .. $#records+1);
5396 my @inst_values = ();
5397 my @inst_positions = ();
5399 my ( $glob_value, $glob_position );
5400 INSTANCES
: foreach my $j ( @instances ) {
5401 if ( defined $records[ $j-1 ] ) {
5403 my ( $value, $position );
5404 foreach my $option ( @
{$records[$j-1] -> {'options'}} ) {
5405 if ( defined $option and $option -> name
eq $name) {
5406 if ( $global_position ) {
5407 $glob_value = $option -> value
;
5408 $glob_position = $glob_pos;
5411 $value = $option -> value
;
5418 push( @inst_values, $value );
5419 push( @inst_positions, $position );
5421 'debug' -> die( message
=> "Instance $j in problem number $i does not exist!" )
5424 if ( $global_position ) {
5425 push( @values, $glob_value );
5426 push( @positions, $glob_position );
5428 push( @values, \
@inst_values );
5429 push( @positions, \
@inst_positions );
5432 'debug' -> die( message
=> "Problem number $i does not exist!" );
5435 # if( defined $problem_number ) {
5436 # if( $problem_number < 1 or $problem_number > scalar @problems ) {
5437 # die "model -> _get_option_val_pos: No such problem number, ",
5438 # $problem_number,", in this model!\n";
5442 # die "modelfile -> _get_option_val_pos: No problem $problem_number exists\n"
5443 # if( (scalar @problems < 1) and ($problem_number ne 'all') );
5445 # foreach my $problem ( @problems ) {
5446 # @records = @{$problem -> $accessor};
5447 # @records = ($records[$instance-1]) if ( $instance ne 'all' );
5448 # die "modelfile -> _get_option_val_pos: No record instance $instance ".
5449 # "of record $record_name in problem $problem_number exists\n"
5450 # if( (scalar @records < 1) and ($instance ne 'all') );
5451 # foreach my $record ( @records ) {
5453 # foreach my $option ( @{$record -> {'options'}} ) {
5454 # if ( defined $option and $option -> name eq $name) {
5455 # print "Found $name at $i\n" if ( $self -> {'debug'} );
5456 # push( @values, $option -> value );
5457 # push( @positions, $i );
5464 end _get_option_val_pos
5466 # }}} _get_option_val_pos
5472 # The I<add_if_absent> argument tells the method to add an init (theta,omega,sigma)
5473 # if the parameter number points to a non-existing parameter with parameter number
5474 # one higher than the highest presently included. Only applicatble if
5475 # I<new_values> are set. Default value = 0;
5477 unless( scalar @problem_numbers > 0 ){
5478 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5480 my @problems = @
{$self -> {'problems'}};
5481 if ( $#new_values >= 0 ) {
5482 'debug' -> die( message
=> "The number of new value sets " .
5483 ($#new_values+1) . " do not" .
5484 " match the number of problems " . ($#problem_numbers+1) . " specified" )
5485 unless(($#new_values == $#problem_numbers) );
5486 if ( $#parameter_numbers > 0 ) {
5487 'debug' -> die( message
=> "The number of parameter number sets do not" .
5488 " match the number of problems specified" )
5489 unless(($#parameter_numbers == $#problem_numbers) );
5493 my $new_val_idx = 0;
5494 foreach my $i ( @problem_numbers ) {
5495 if ( defined $problems[ $i-1 ] ) {
5496 if ( scalar @new_values > 0) {
5498 # Use attribute parameter_values to collect diagnostic outputs
5499 push( @parameter_values,
5500 $problems[ $i-1 ] ->
5501 _init_attr
( parameter_type
=> $parameter_type,
5502 parameter_numbers
=> $parameter_numbers[ $new_val_idx ],
5503 new_values
=> \@
{$new_values[ $new_val_idx ]},
5504 attribute
=> $attribute,
5505 add_if_absent
=> $add_if_absent ) );
5508 # {{{ Retrieve values
5509 push( @parameter_values,
5510 $problems[ $i-1 ] ->
5511 _init_attr
( parameter_type
=> $parameter_type,
5512 parameter_numbers
=> $parameter_numbers[ $i-1 ],
5513 attribute
=> $attribute ) );
5514 # }}} Retrieve values
5517 'debug' -> die( message
=> "Problem number $i does not exist!" );
5532 # $modobj -> _option_name ( record => $record_name,
5535 # This basic usage returns the name of the third option in the first
5536 # instance of the record specified by I<record>.
5539 my ( @problems, @records, @options, $i );
5540 my $accessor = $record.'s';
5541 if ( defined $self -> {'problems'} ) {
5542 @problems = @
{$self -> {'problems'}};
5544 'debug' -> die( message
=> "No problems defined in model" );
5546 if ( defined $problems[$problem_number - 1] -> $accessor ) {
5547 @records = @
{$problems[$problem_number - 1] -> $accessor};
5549 'debug' -> die( message
=> "No record $record defined in ".
5550 "problem number $problem_number." );
5552 if ( defined $records[$instance - 1] -> options
) {
5553 @options = @
{$records[$instance - 1] -> options
};
5555 'debug' -> die( message
=> "model -> _option_name: No option defined in record ".
5556 "$record in problem number $problem_number." );
5559 foreach my $option ( @options ) {
5560 if ( $i == $position ) {
5561 if ( defined $new_name ){
5562 $option -> name
($new_name) if ( defined $option );
5564 $name = $option -> name
if ( defined $option );
5574 # {{{ _parameter_count
5575 start _parameter_count
5577 if( defined $self -> {'problems'} ){
5578 my $problems = $self -> {'problems'};
5579 if( defined @
{$problems}[$problem_number - 1] ){
5580 $count = @
{$problems}[$problem_number - 1] -> record_count
( 'record_name' => $record );
5584 end _parameter_count
5585 # }}} _parameter_count
5587 # {{{ _read_problems
5589 start _read_problems
5592 # To read problems from a modelfile we need its full name
5593 # (meaning filename and path). And we need an array for the
5594 # modelfile lines and an array with indexes telling where
5595 # problems start in the modelfile array.
5598 my $file = $self -> full_name
;
5599 my ( @modelfile, @problems );
5600 my ( @problem_start_index );
5602 # Check if the file is missing, and if that is ok.
5603 # TODO Check accessor what happens if the file is missing.
5605 return if( not (-e
$file) && $self -> {'ignore_missing_files'} );
5607 # Open the file, slurp it and close it
5608 open( FILE
, "$file" ) ||
5609 'debug' -> die( message
=> "Model -> _read_problems: Could not open $file".
5611 @modelfile = <FILE
>;
5614 my @extra_data_files = defined $self ->{'extra_data_files'} ?
5615 @
{$self -> {'extra_data_files'}} : ();
5616 my @extra_data_headers = defined $self ->{'extra_data_headers'} ?
5617 @
{$self -> {'extra_data_headers'}} : ();
5620 # # Find the indexes where the problems start
5621 # for ( my $i = 0; $i <= $#modelfile; $i++ ) {
5622 # push( @problem_start_index, $i )if ( $modelfile[$i] =~ /\$PROB/ );
5625 # # Loop over the number of problems. Copy the each problems lines
5626 # # and create a problem object.
5628 # for( my $i = 0; $i <= $#problem_start_index; $i++ ) {
5629 # my $start_index = $problem_start_index[$i];
5630 # my $end_index = defined $problem_start_index[$i+1] ? $problem_start_index[$i+1] - 1: $#modelfile ;
5632 # my @problem_lines = @modelfile[$start_index .. $end_index];
5634 # # Problem object creation.
5635 # push( @problems, model::problem -> new ( debug => $self -> {'debug'},
5636 # ignore_missing_files => $self -> {'ignore_missing_files'},
5637 # prob_arr => \@problem_lines,
5638 # extra_data_file_name => $extra_data_files[$i],
5639 # extra_data_header => $extra_data_headers[$i]) );
5641 my $start_index = 0;
5646 # It may look like the loop takes one step to much, but its a
5647 # trick that helps parsing the last problem.
5648 for ( my $i = 0; $i <= @modelfile; $i++ ) {
5649 if( $i <= $#modelfile ){
5650 $_ = $modelfile[$i];
5653 # In this if statement we use the lazy evaluation of logical
5654 # or to make sure we only execute search pattern when we have
5655 # a line to search. Which is all cases but the very last loop
5658 if( $i > $#modelfile or /\$PROB/ ){
5661 # The if statement here is only necessary in the first loop
5662 # iteration. When start_index == end_index == 0 we want to
5663 # skip to the next iteration looking for the actual end of
5664 # the first problem.
5666 if( $end_index > $start_index and not $first ){
5667 # extract lines of code:
5668 my @problem_lines = @modelfile[$start_index .. $end_index-1];
5669 # reset the search for problems by moving the problem start
5673 my $sh_mod = model
::shrinkage_module
-> new
( model
=> $self,
5674 temp_problem_number
=> ($#problems+2));
5675 my $prob = model
::problem
->
5676 new
( directory
=> $self -> {'directory'},
5677 ignore_missing_files
=> $self -> {'ignore_missing_files'},
5678 ignore_missing_output_files
=> $self -> {'ignore_missing_output_files'},
5679 sde
=> $self -> {'sde'},
5680 cwres
=> $self -> {'cwres'},
5681 mirror_plots
=> $self -> {'mirror_plots'},
5682 nm_version
=> $self -> {'nm_version'},
5683 prob_arr
=> \
@problem_lines,
5684 extra_data_file_name
=> $extra_data_files[$prob_num],
5685 extra_data_header
=> $extra_data_headers[$prob_num],
5686 shrinkage_module
=> $sh_mod );
5687 push( @problems, $prob );
5688 if ( $self -> cwres
() ) {
5690 if ( defined $self -> extra_output
() ) {
5691 @eo = @
{$self -> extra_output
()};
5693 if( $prob -> {'cwres_modules'} ){
5694 push( @eo, @
{$prob -> {'cwres_modules'} -> [0] -> cwtab_names
()} );
5696 $self -> extra_output
( \
@eo );
5699 $sh_mod -> problem
( $problems[$#problems] );
5706 # Set the problems in the modelobject.
5707 $self -> problems
(\
@problems);
5711 # }}} _read_problems
5717 unless( $#problem_numbers >= 0 ){
5718 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5721 my @problems = @
{$self -> {'problems'}};
5722 foreach my $i ( @problem_numbers ) {
5723 if ( defined $problems[ $i-1 ] ) {
5724 my $found = $self -> is_option_set
( 'problem_number' => $i,
5725 'record' => $record_name,
5726 'name' => $option_name,
5727 'fuzzy_match' => $fuzzy_match );
5728 $problems[$i-1] -> remove_option
( record_name
=> $record_name,
5729 option_name
=> $option_name,
5730 fuzzy_match
=> $fuzzy_match ) if ( $found );
5731 $problems[$i-1] -> add_option
( record_name
=> $record_name,
5732 option_name
=> $option_name,
5733 option_value
=> $option_value );
5745 unless( $#problem_numbers >= 0 ){
5746 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5749 my @problems = @
{$self -> {'problems'}};
5750 foreach my $i ( @problem_numbers ) {
5751 if ( defined $problems[ $i-1 ] ) {
5752 $problems[$i-1] -> add_option
( record_name
=> $record_name,
5753 option_name
=> $option_name,
5754 option_value
=> $option_value,
5755 add_record
=> $add_record );
5767 unless( $#problem_numbers >= 0 ){
5768 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5771 my @problems = @
{$self -> {'problems'}};
5772 foreach my $i ( @problem_numbers ) {
5773 if ( defined $problems[ $i-1 ] ) {
5774 $problems[$i-1] -> remove_option
( record_name
=> $record_name,
5775 option_name
=> $option_name,
5776 fuzzy_match
=> $fuzzy_match);
5784 # {{{ _option_val_pos
5786 start _option_val_pos
5788 unless( $#problem_numbers >= 0 ){
5789 @problem_numbers = (1 .. $#{$self -> {'problems'}}+1);
5791 my @problems = @
{$self -> {'problems'}};
5792 if ( $#new_values >= 0 ) {
5793 'debug' -> die( message
=> "Trying to set option $name in record $record_name but the ".
5794 "number of new value sets (".
5796 "), do not match the number of problems specified (".
5797 ($#problem_numbers+1).")" )
5798 unless(($#new_values == $#problem_numbers) );
5799 if ( $#instance_numbers > 0 ) {
5800 'debug' -> die( message
=> "The number of instance number sets (".
5801 ($#instance_numbers+1).
5802 "),do not match the number of problems specified (".
5803 ($#problem_numbers+1).")" )
5804 unless(($#instance_numbers == $#problem_numbers) );
5808 foreach my $i ( @problem_numbers ) {
5809 if ( defined $problems[ $i-1 ] ) {
5810 my $rn_ref = $#instance_numbers >= 0 ? \@
{$instance_numbers[ $i-1 ]} : [];
5811 if ( scalar @new_values > 0) {
5814 if( not defined $new_values[ $i-1 ] ) {
5815 debug
-> die( message
=> " The specified new_values was undefined for problem $i" );
5818 if( not ref( $new_values[ $i-1 ] ) eq 'ARRAY' ) {
5819 debug
-> die( message
=> " The specified new_values for problem $i is not an array as it should be but a ".
5820 ( defined ref( $new_values[ $i-1 ] ) ?
5821 ref( $new_values[ $i-1 ] ) : 'undef' ) );
5824 $problems[ $i-1 ] ->
5825 _option_val_pos
( record_name
=> $record_name,
5826 instance_numbers
=> $rn_ref,
5827 new_values
=> \@
{$new_values[ $i-1 ]},
5829 exact_match
=> $exact_match );
5833 # {{{ Retrieve values
5834 my ( $val_ref, $pos_ref ) =
5835 $problems[ $i-1 ] ->
5836 _option_val_pos
( record_name
=> $record_name,
5837 instance_numbers
=> $rn_ref,
5839 exact_match
=> $exact_match );
5840 push( @values, $val_ref );
5841 push( @positions, $pos_ref );
5842 # }}} Retrieve values
5845 'debug' -> die( message
=> "Problem number $i does not exist!" );
5851 # }}} _option_val_pos
5853 # {{{ subroutine_files
5855 start subroutine_files
5858 foreach my $subr( 'PRED','CRIT', 'CONTR', 'CCONTR', 'MIX', 'CONPAR', 'OTHER', 'PRIOR' ){
5859 my ( $model_fsubs, $junk ) = $self -> _option_val_pos
( record_name
=> 'subroutine',
5861 if( @
{$model_fsubs} > 0 ){
5862 foreach my $prob_fsubs ( @
{$model_fsubs} ){
5863 foreach my $fsub( @
{$prob_fsubs} ){
5870 # BUG , nonmem6 might not require the file to be named .f And I've
5871 # seen examples of files named .txt
5873 @fsubs = keys %fsubs;
5875 for( my $i = 0; $i <= $#fsubs; $i ++ ){
5876 unless( $fsubs[$i] =~ /\.f$/ ){
5882 end subroutine_files