From dc8835882ab83925e68b5e5a1ba1dabb03cd84b1 Mon Sep 17 00:00:00 2001
From: pontus_pih bootstrap -samples=200 run89.mod bootstrap -samples=200 run89.mod bootstrap -samples=2000 -bca run89.mod bootstrap -samples=2000 -bca run89.mod bootstrap -samples=2000 -bca -stratify_on=5 run89.mod bootstrap -samples=2000 -bca -stratify_on=5 run89.mod -samples -samples -sample_size -sample_size -bca -bca -stratify_on=integer|string -stratify_on=integer|string -skip_covariance_step_terminated -skip_covariance_step_terminated -skip_with_covstep_warnings -skip_with_covstep_warnings -skip_minimization_terminated -skip_minimization_terminated -skip_estimate_near_boundary -skip_estimate_near_boundary -estimate_near_boundary_limit='number' -estimate_near_boundary_limit='number' -covariance_step_successful_limit='number' -covariance_step_successful_limit='number' -covariance_step_warnings_limit='number' -covariance_step_warnings_limit='number' -minimization_successful_limit='number' -minimization_successful_limit='number' -mplots -mplots -rplots -rplots -h | -? -help -bins=$number -selection_method='random' or 'consecutive' -case_column=column_name|column_number -rplots -rplots -xv|-noxv llp -model=run89.mod -thetas='1,2' llp run89.mod -thetas='1,2' llp -model=run89.mod -thetas='1,2' -rse_thetas='20,30' llp run89.mod -thetas='1,2' -rse_thetas='20,30' -model='filename' -outputfile='filename' -outputfile=filename -significant_digits=integer
- The Boostrap creates a log file and a result file. Both are by default placed in the bootstrap_dirX directory
- and are called boostraplog.csv and bootstrap-results.csv.
-
+ The Bootstrap creates a log file and a result file. Both are by default placed in the bootstrap_dirX directory
+ and are called boostraplog.csv and bootstrap_results.csv.
+
-As PsN is a fairly complex piece of software, bugs do emerge. Here is
-what you can do if you encounter one.
-
-If PsN crashes, you get a weird error message, have erroneous output
-or something that is just plain odd? If you think its a bug, submit it
-and it will be investigated. Before you do, make sure it has not
-been submitted already. First check the list below, then search the mailing
-list archives, and check the SourceForge
-bug tracker for PsN. If you don't have time for this, submit the
-bug anyway.
-
-The best way to submit a bug is to send a message to
-the PsN-general mailing list, or to one of the authors. Try to
-describe, in reasonable detail, what the bug is and what you did when
-i appeared. Also your PsN version and name of operating system and
-anything that might be helpful. From there we will try to help you
-out. Maybe you will also get help from other users on the mailing
-list. Do not send model files and data files unless we ask you to.
-
-Bugs should generally be fixed as soon as possible. Some bugs, however,
-would require rewriting larger parts of the code or risk breaking
-behavior in other code bits. Those bugs make the list on this
-page. When possible a workaround is given, otherwise be patient,
-eventually these bugs will be fixed.
+As PsN is a fairly complex piece of software, bugs do emerge. Here is
+what you can do if you encounter one.
+
+If PsN crashes, if you get a weird error message, if you get an erroneous output
+or if you experience something that is just plain odd (but still PsN-related... :-) ), what should you do? If you think that it really is a bug, submit it
+and it will be investigated. Before you do, make sure it has not
+been submitted already. First check the list below, then search the mailing
+list archives, and check the SourceForge
+bug tracker for PsN. If you don't have time for this, submit the
+bug anyway.
+
+The best way to submit a bug is to send a message to
+the PsN-general mailing list, or to one of the authors. Try to
+describe, in reasonable detail, what the bug is and what you did when
+i appeared. Also, add your PsN version, the name of your operating system (e.g. Windows XP or Mac OS X) and
+anything that might be helpful. From there we will try to help you
+out. Maybe you will also get help from other users on the mailing
+list. Do not send model files and data files unless we ask you to.
+
+Our aim is to get bugs fixed as soon as possible. To fix some bugs, however,
+would require rewriting larger parts of the code or risk breaking
+behavior in other code bits. Those bugs make the list on this
+page. When possible, a workaround is given, otherwise be patient,
+eventually these bugs will be fixed. The Case-deletion Diagnostics tool is run from the command line
-with a few mandatory arguments. It is run as a diagnostic after
-a model is regarded finished or at least mature enough for validation. You need to specify the NONMEM model file
-with a model that has successful termination. You also have to
-specify the number or the name of the column in the data file, on which to
-select for deletion. This is done with the case_column option.
-The options are given here in their long form. Any option may be
-abbreviated to any nonconflicting prefix. The -threads option
-may be abbreviated to -t (or even -thr) but -debug may not be
-abbreviated to -d because it conflicts with -debug_packages and-debug_subroutines. The following options are valid: -h | -? With -h or -? cdd will print a list of options and then exit. -help With -help cdd will print a longer help message. -bins=number Sets the number of data bins or cdd data sets that should be used. If the
- number of unique values or factors in the based_on column is
- higher than the number of bins, one or more factors will be
- deleted in each of the cdd data set. Specifying bins as higher than
- the number of factors will have no effect. In that case the bin number will be
- set to the number of factors.
- The default value is equal to the number of unique values in the based_on column. -selection_method='random' or 'consecutive' Specifies whether the factors selected for exclusion should be
- drawn randomly or consecutively from the data file.
- Default value = 'consecutive' -case_column=column_name|column_number See the execute documentation for a description of common options. The Case-deletion Diagnostics tool creates a log file and a result file. Both are by default placed in the cdd_dirX directory and are called cdd.csv and cdd-results.csv. Example
- cdd modelfile.mod -case_column=10
-
- This will perform a Case-deletion Diagnostic based on the factors in column number ten. If,
- for example, that column holds the names of the seven centers
- included in the study, this command will create seven copies of
- the data set, each with individuals from one specific
- center deleted. Say that the centers are numbered 1 to 7. Then
- all individuals from center 1 will be excluded from data set 1, the individuals from center 2 will be excluded from data set 2, and so on.
-
PsN is distributed as a gziped tar ball and zipped file. Both should work
-on both Windows and UNIX.bootstrap
- Perl script for non-parametric boostrap of NONMEM runs.
+ Perl script for non-parametric bootstrap of NONMEM runs.
Usage:
EOF
@@ -81,7 +81,7 @@ EOF
$help_text{Examples} = <<'EOF';
Example:
- Description
- The Case Deletion Diagnostics tool is run from the command line
+ The Case Deletion Diagnostics tool is run using the command from the command line
with a few mandatory arguments. CDD is run as a diagnostic after
a model is regarded finished or at least mature enough to run
validation tool on. You need to specify the NONMEM modelfile
@@ -61,7 +56,7 @@ $help_text{Description} = <<'EOF';
EOF
$help_text{Examples} = <<'EOF';
- Example:
+Examples
cdd -model=run89.mod -case_column=10
@@ -75,8 +70,8 @@ $help_text{Examples} = <<'EOF';
2 individuals from center 2 and so on.
EOF
-$help_text{Options} = <<'EOF';
- Options:
+$help_text{Options} = <<'EOF';
+ Options
The options are given here in their long form. Any option may be
abbreviated to any nonconflicting prefix. The -threads option
@@ -88,19 +83,19 @@ $help_text{Options} = <<'EOF';
EOF
$help_text{-h} = <<'EOF';
- -h | -?
+ Example:
- Description:
The Stepwise Covariate Model (SCM) building tool of PsN implements
@@ -69,19 +74,17 @@ EOF
followed by Backward Elimination, which proceeds as the Forward
Selection but reversely, using stricter criteria for model
improvement.
-
- The Stepwise Covariate Model building procedure is run by the scm
- utility. The options to the scm utility are of three diffrent
- types, first are the common options which works like the common
- options for all tools. Then are the SCM specific command line
- options. And last are options which have a more complex structures
- and are considered to cumbersome to specify on the command
- line. These options must therefore be specified in a separate
- configuration file. It is possible to provide values for all
- options, including the common options, in the configuration file
- but it should be noted that the command line overrides the
- configuration file, if an option is specified at both
- locations.
+
+
+
+ The Stepwise Covariate Model building procedure is run by the PsN
+ tool scm. The options to scm can (and should) be rather complex to
+ describe all features of a covariate model building procedure. To
+ make it easier for the user, a configuration file should be
+ written for each scm run. The options can be specified in this
+ file instead of the command line.
+
@@ -200,11 +203,6 @@ EOF
common_options::online_help( 'scm', \%options, \%help_text, \%required_options, \%optional_options);
-debug -> level( $options{'debug'} );
-debug -> package( $options{'debug_package'} );
-debug -> subroutine( $options{'debug_subroutine'} );
-debug -> warn_with_trace( $options{'warn_with_trace'} );
-
if ( $options{'config_file'} eq '' ){
print "Please specify a config file \n";
exit;
@@ -213,6 +211,11 @@ if ( $options{'config_file'} eq '' ){
'ui' -> category( 'scm' );
'ui' -> silent(1) if( $options{'silent'} );
+debug -> level( $options{'debug'} );
+debug -> package( $options{'debug_package'} );
+debug -> subroutine( $options{'debug_subroutine'} );
+debug -> warn_with_trace( $options{'warn_with_trace'} );
+
my $config_file;
if( -e $options{'config_file'} ){
my $file = file -> new( name => $options{'config_file'}, path => '.' );
diff --git a/bin/setup.pl b/bin/setup.pl
index b94d5c6..16bbd9b 100644
--- a/bin/setup.pl
+++ b/bin/setup.pl
@@ -3,14 +3,14 @@ use Config;
use CPAN;
use File::Spec;
-my $version = '2.2.2';
+my $version = '2.2.4';
my $name_safe_version = $version;
$name_safe_version =~ s/\./_/g;
my @utilities = ('bootstrap', 'cdd', 'execute', 'llp', 'scm', 'sumo', 'mcs', 'mc_cdd',
'data_stats', 'create_extra_data_model', 'single_valued_columns',
'gam42toconf', 'create_cont_model', 'create_cont_data', 'unwrap_data', 'create_subsets',
- 'check_termination' );
+ 'check_termination','se_of_eta','update_inits' );
my @win_modules = ('Math::Random');
my @nix_modules = ('Math::Random','Storable');
diff --git a/diagrams/cdd.dia b/diagrams/cdd.dia
index 7e52709..e108c17 100644
--- a/diagrams/cdd.dia
+++ b/diagrams/cdd.dia
@@ -346,7 +346,7 @@
Output
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Output
+
+
+
+
+
+
diff --git a/html/buglist.php b/html/buglist.php
index e2b36f4..b0fdbf5 100755
--- a/html/buglist.php
+++ b/html/buglist.php
@@ -1,320 +1,312 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Bugs
-Submitting
-a bug
-Bug list
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bugs
+Submitting
+a bug
+Bug list
+
+
+
+
+
+
+
+
diff --git a/html/cdd_docs.php b/html/cdd_docs.php
index 83f81e9..d76df84 100755
--- a/html/cdd_docs.php
+++ b/html/cdd_docs.php
@@ -1,326 +1,219 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-Synopsis
-$ cdd [ -h | -? ] [ --help ]
---case_column='column_name|column_number'
-[ --bins=integer ]
-[ --selection_method=''random'|'consecutive'' ]
-[ --abort_on_fail ]
-[ --clean ]
-[ --compress ]
-[ --cpu_time=integer ]
-[ --debug=0 ]
-[ --debug_package='string' ]
-[ --debug_subroutine='string' ]
-[ --directory='string' ]
-[ --extra_data_file='string' ]
-[ --extra_files='string' ]
-[ --grid_batch_size=integer ]
-[ --missing_data_token='string' ]
-[ --nm_directory='string' ]
-[ --nm_version='string' ]
-[ --outputfile='string' ]
-[ --picky ]
-[ --remove_temp_files ]
-[ --results_file='string' ]
-[ --retries=integer ]
-[ --run_on_nordugrid ]
-[ --seed='string' ]
-[ --threads=integer ]
-[ --tweak_inits ]
-Description
-Options
-Output
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/html/download.php b/html/download.php
index 721fc82..d8eaf76 100755
--- a/html/download.php
+++ b/html/download.php
@@ -121,7 +121,7 @@ MM_reloadPage(true);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- | Mostly bug fixes. See the README.txt for details. | -2006-11-07 |
+ + | Please see the change log or the README.txt file for details. | +2007-09-10 |
+ |
|
- 2006-11-07 |
+ 2007-09-10 |
||
@@ -170,16 +170,50 @@ on both Windows and UNIX. | |||||
- | The new 2.2.0 release |
- 2006-08-09 |
+ + | Please see the change log or the README.txt file for details. | +2007-04-30 |
+ |
|
- 2006-08-09 |
+ 2007-04-30 |
||
+ | Includes a rather large re-write of the jobs submission. Memory foot print should be much lower. See the README.txt for details. | +2007-03-05 |
+ |||
+ |
|
+ 2007-03-05 |
+ |||
+ | |||||
+ | Version 2.2.1 |
+ 2006-11-07 |
+ |||
+ |
|
+ 2006-11-07 |
+ |||
+ | The new 2.2.0 release |
+ 2006-08-09 |
+ |||
+ |
|
+ 2006-08-09 |
+ |||
|
|||||
We have begun to release beta tests of the stable releases. In these we will include all bug fixes and feature additions that we think are suitable to add quickly to the stable branch. |
|||||
- | First beta of the 2.2.2 release. |
- 2006-11-08 |
+ + | 4:th beta of the 2.2.2 release. Please use the stable release 2.2.3. It is newer than this beta release. |
+ 2007-01-29 |
+ |
|
- 2006-11-08 |
+ 2007-01-29 |
||
|
@@ -210,7 +244,7 @@ on both Windows and UNIX.
|||||
There is currently no development version available, but we are planning to implement some interresting features and a release - of 2.3.0 might apear here then. |
+ of 2.3.0 might appear here then.
PsN is tested with Perl 5.8.4 and 5.8.6 to 5.8.8 on -Linux. On Windows its tested with ActiveState -ActivePerl 5.6.8.811. To compile NONMEM GNU G77 version 3.3.5 and Compaq's PsN is tested on various platfiorms. +
+ | Operating system version | +Perl | +NONMEM | +Fortran compiler | +
---|---|---|---|---|
Microsoft Windows | +XP | +ActiveState ActivePerl 5.6.8.811 and 5.8.8.819 | +5 and 6 | +Digital Visual + Fortran version 6.5 | +
+ | 2000 | +ActiveState ActivePerl 5.6.8.811 and 5.8.8.819 | +5 and 6 | +Digital Visual
-Fortran version 5.0 have been tested.
- PsN development is done under Linux, therefore the function under -Windows is less tested. + Fortran version 6.5 |
+
Macintosh | +OS X 10.4.7 and above | +5.8.6 and 5.8.8 | +5 and 6 | +Intel Fortran 9.1 | +
Linux | +Red Hat 9, Gentoo | ++ | 5 and 6 | +GNU g77 2.96 and 3.3 | +
+ | + | + | + | + |
+
-One aim of PsN is to make it platform independent. So please do try +Our aim is to make PsN platform independent. Please try PsN on other platforms and with other Perl versions and compilers and report your success or failure. -
Installation is easy and consists of five simple @@ -272,8 +350,8 @@ script
Run the installation script from within PsN-Source. If you are running windows and have ActiveState - ActivePerl installed you should be able to double click on - setup.pl. Otherwise open a command line window, go to + ActivePerl installed you should be able to double-click on + setup.pl. Otherwise open a command line window (Windows Start->Run, type 'cmd'), go to the PsN-Source directory and type:
perl setup.pl
@@ -283,54 +361,49 @@ scriptAnswer the questions on screen. The default is probably the - best for most users. If you cannot install PsN were the install + best for most users. If you cannot install PsN where the install script suggests and you wish to use PsN in your own perl scripts, you must make sure that the directory where you installed the PsN core and toolkit is in Perl's include - path. For convenience You should also check that the directory - where the utilities are installed is in your search path. -
- + path. For convenience you should also check that the directory + where the utilities are installed is in your search path.Edit the configuration file - (PsN-installdir/PsN/psn.conf) to make PsN aware your NONMEM - installation:
For a more detailed documentation of the psn.conf look here.
+Edit the configuration file psn.conf to make PsN aware your NONMEM + installation. If you accept the default options in the PsN setup script, this file is usually found in C:\Perl\site\lib\PsN_version_number\ (Windows) or /usr/local/lib/perl5/site_perl/perl_version/PsN_version/ or /usr/lib/perl5/site_perl/perl_version/PsN_version/ (Linux and Macintosh).
For a more detailed documentation of the psn.conf look here.
-[nm_versions]
-
- 5=/export/home/nmv1.1
-
- 5_big=/export/home/nmv1.1_big
+
[nm_versions]
+ default=/export/home/nmvi1.0,6
+5=/export/home/nmv1.1,5
+5_big=/export/home/nmv1.1_big,5
+ 6=/export/home/nmvi1.0
+
[compiler]
; Gnu fortran compiler
name=g77
- options=-W -static -O
-
-
The header [nm_versions] must always be present. Each -line under the nm_version header corresponds to a NONMEM version. To -the left of the equal sign is a version identifier which is a number -or a text that identifies an installation of NONMEM. This is the -identifier you give to the PsN utilities using the option -nm_version. -To the right is the directory where the version of NONMEM is installed.
- + options=-W -static -O + +The header [nm_versions] must always be present. Each + line under the nm_version header corresponds to a NONMEM version. To + the left of the equal sign is an identifier which is a number + or a text that names an installation of NONMEM. This is what you give to the PsN utilities using the option -nm_version. + Next comes the directory where the version of NONMEM is installed. Last is a version number. This is new from PsN version 2.2.2 and is needed for the computation of conditional weighted residuals.
+The [compiler] section is optional but necessary if you have -another compiler than g77. The compiler section has two -lines. One starting with name on the left of the equal sign -which is the compiler executable name. You should include a path if you -don't have the compiler directory in you environment path. The second -line is the options line where you specify compiler options, -such as optimizations. (Note that -lines starting with ; are ignored.)
- -The new version 2.2 is now available for download.
-Perl-speaks-NONMEM -Perl-speaks-NONMEM (PsN) is a collection of Perl modules and programs aiding in the development - of non-linear mixed effect models using NONMEM. The functionality ranges from solutions to simpler - tasks such as parameter estimate extraction from output files, data file sub setting and resampling, - to advanced computer-intensive statistical methods. PsN includes stand-alone tools for the end-user - as well as development libraries for method developers. -
-- Compared to previous versions of PsN 2, the ongoing work on PsN version 2.2 has brought some changes - to the overall structure. PsN is now logically divided into three parts. Note, however, that you still - only download and install one package. -
--Most of what was included in the 2.0 release of PsN is now included in PsN-Core. PsN-Core is built around NONMEM's model, data and output -files. Through PsN-Core -all parts of these files can be controlled in user-written Perl code.
--Using the functionality of PsN-Core we have implemented two new components: PsN-Toolkit and PsN-Utilities.
-PsN-Toolkit is a collection - of computer intensive statistical methods for non-linear mixed effect modeling using NONMEM. The toolkit includes Perl modules for Bootstrapping, Jackknifing, Log-likelihood Profiling, Case-deletion Diagnostics and Stepwise Covariate Model building. Using a module from PsN-Toolkit requires some basic - knowledge of Perl and some understanding of the toolkit framework.
-PsN-Utilities is a set of command line programs -that allows the user to use the functionality of PsN-Core and PsN-Toolkit without the need to write Perl code. Apart from programs for all the tools in PsN-Toolkit, PsN-Utilities includes utilities that perform simpler tasks, such as summarizing the output from NONMEM -runs. -
-You can read more about the different parts under Documentation.
--Perl-speaks-NONMEM is copyright © 2000-2006 by Lars Lindbom -and Niclas -Jonsson. All rights reserved. -
--PsN is maintained by Pontus -Pihlgren and Lars -Lindbom. -
-The site is designed and implemented -by Justin -Wilkins. -
--Perl-speaks-NONMEM is licensed under version 2 of the GNU General -Public License as published by the Free Software Foundation. -
--NONMEM® is a registered trademark of GloboMax. The Perl camel -logo is -a registered trademark of O'Reilly Media, Inc. and is used with -permission. All logos and trademarks in this site are property of -their respective owners. -
-- | PsN is hosted at SourceForge. | -
-
-
-
|
- |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- |
Version 2.2.4 is available here.
+New features
+- Simulated data suitable for creating mirror plots can be generated + by using a new options called --mirror_plots. The option takes a + value which defines the number of simulations that will be + generated.
+- A new option, --iofv, enables the computation of individual + objective function values. These values are printed to a table file + called iotab*, where * is the same number as is defined for any + sdtab or patab tables. These names correspond to the normal Xpose + table file format. If no sdtab or patab table is found in the + NONMEM control stream, the iotab file is given number 1.
+- A brand new user command update_inits that will put + final estimates from a NONMEM output file and put into a given + model file. This is quite experimental. PsN will reformat the model + file quite a lot and comments in the file might get lost. Your model + file will be copied with the addition of a ".org" extension, so you + wont lose your model.
+- "--compute_cwres" option renamed to simply "--cwres"
+ +Bug Fixes
+- As usual a few bugs were found and fixed between 2.2.3 and 2.2.4. Please read the change logs. These are also available in the README.txt file included in the release packege as usual. The most important bug fixes are that PsN now works properly on Windows 2000 and fixes to the Sun Grid Engine interface(Thanks to Jeroen Elassaiss and Stefan Verhoeven).
+Perl-speaks-NONMEM
+Perl-speaks-NONMEM (PsN) is a collection of Perl modules and programs aiding in the development + of non-linear mixed effect models using NONMEM. The functionality ranges from solutions to simpler + tasks such as parameter estimate extraction from output files, data file sub setting and resampling, + to advanced computer-intensive statistical methods. PsN includes stand-alone tools for the end-user + as well as development libraries for method developers. +
++ Compared to previous versions of PsN 2, the ongoing work on PsN version 2.2 has brought some changes + to the overall structure. PsN is now logically divided into three parts. Note, however, that you still + only download and install one package. +
++Most of what was included in the 2.0 release of PsN is now included in PsN-Core. PsN-Core is built around NONMEM's model, data and output +files. Through PsN-Core +all parts of these files can be controlled in user-written Perl code.
++Using the functionality of PsN-Core we have implemented two new components: PsN-Toolkit and PsN-Utilities.
+PsN-Toolkit is a collection + of computer intensive statistical methods for non-linear mixed effect modeling using NONMEM. The toolkit includes Perl modules for Bootstrapping, Jackknifing, Log-likelihood Profiling, Case-deletion Diagnostics and Stepwise Covariate Model building. Using a module from PsN-Toolkit requires some basic + knowledge of Perl and some understanding of the toolkit framework.
+PsN-Utilities is a set of command line programs +that allows the user to use the functionality of PsN-Core and PsN-Toolkit without the need to write Perl code. Apart from programs for all the tools in PsN-Toolkit, PsN-Utilities includes utilities that perform simpler tasks, such as summarizing the output from NONMEM +runs. +
+You can read more about the different parts under Documentation.
++Perl-speaks-NONMEM is copyright © 2000-2005 by Lars Lindbom +and Niclas +Jonsson and 2006-2007 by Lars Lindbom. All rights reserved. +
++PsN is maintained by Pontus +Pihlgren and Lars +Lindbom. +
+The site is designed and implemented +by Justin +Wilkins. +
++Perl-speaks-NONMEM is licensed under version 2 of the GNU General +Public License as published by the Free Software Foundation. +
++NONMEM® is a registered trademark of GloboMax. The Perl camel +logo is +a registered trademark of O'Reilly Media, Inc. and is used with +permission. All logos and trademarks in this site are property of +their respective owners. +
++ | PsN is hosted at SourceForge. | +
+
+
+
|
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+ |
diff --git a/html/scm_docs.php b/html/scm_docs.php index bc83e9b..453c53d 100755 --- a/html/scm_docs.php +++ b/html/scm_docs.php @@ -1,627 +1,459 @@ - - - -
Valid states for the parameter-covariate relations
- -The SCM tool in PsN is written to be flexible in the shape of the -parameter-covariate relations. Currently there is a fixed set of -available forms of relations but there is ongoing development aiming -at full flexibility for the user with regard to relation-shape -definitions.
- -The avaialable shapes or states for the -parameter-covariate relations for continuous covariates are (1) not -included, (2) included as a linear relation and (3) included as a -piece-wise linear relation with two slopes.
- -Categorical covariates are either (1) not included or (2) included with an extra parameter added for each but the most common category.
-The figures, 1, 2 and 3, are used when specifying included relations below.
- - -The syntax of the simple options is just the name of the option -followed by the equal sign and a valid value for the option. For -example:
- -retries=5
-This states that a maximum of 5 retries will be used in the executions.
-Some options accept Perl code: -base_criteria_values={ 1 => ofv => -9571.234}
-Other take comma-separated lists: -continuous_covariates=AGE,WT,ALBU,BILI,AST,ALT,ALKP,POT,MAG,CA,NA,TOTP
- -Some options don't accept a value on the command line. They set the -behavior of the utility simply by being specified or not. In the -configuration file these options need to be followed by 1 or a 0. A 1 -indicates that it is used and a 0 that it is not used. - -fix=1
-You can place a comment anywhere in the file by prefixing the line with a semicolon: -;ask_if_fail=0
-If an option is long you can break the line with a backslash, just a linebreak will NOT work: -categorical_covariates=SEX,ARR,SHD,NYHA,RACE,ALCO,SMOK,BETA,CGLY,LDIU,\
- TDIU,CANT,ACE,NITR,ACOA,POTA,TWOC,TREA,TWOD,INDU,\
- TUBS,ALQT,ANTP,ANTD,ANTM,ANTH,ANTB,SULP,ANT1,CLIA,\
- CLIB,CLIC,CL3,CIME,METF,FENM,PROC,HEP1,HEP2,HEP3
Simple options
- -The simple options are the SCM specific command line options and the -command line options common to all PsN Utilties. - -List options
- -List options are options that take enumerations of values like the -categorical_covariates option: - -categorical_covariates=SEX,ARR,SHD,NYHA,RAC
- -The list options valid in the configuration file are: - -
categorical_covariates
- -The categorical_covariates list option is -neccessary for the scm to know which type of NONMEM code to generate -for the parameter covariate relation. - -continuous_covariates
- -The categorical_covariates list option is -neccessary for the scm to know which type of NONMEM code to generate -for the parameter covariate relation. - -do_not_drop
- -If the dataset used with the scm is to wide, scm will drop the data -columns that correponds to covariate which is not used in a particular -step. However, if you have used that covariate in code that is not -affected by the scm, NONMEM will produce an error. Therefore it is -neccessary for you to specify which those covariates are, using the -do_not_drop list option. - -extra_files
- -If you need some extraordinary file to be copied into the NONMEM -execution directory, specify them with the extra_files list option. - -Code options
- -Code options are almost like a Simple option. With the difference that -the right side is evaluted by the perl interpretor. If you don't -understand the difference, it is probably not important. However, it -is available for a reason. The SCM have hooks for custom goodness of -fit functions. Those functions may need some special input data. And -for flexibility, we allow that data to be just about anything, the -side effect is that it becomes to complex for the configuration file -structure. The solution is to allow options that are small Perl -programs. Those options we refer to as code options. - -base_criteria_values
- -The base_criteria_values overrides default -criterias for the goodness of fit function used. The default goodness -of fit function takes its base_criteria_value to be the ofv of the -initial model. If you would like to change the base ofv to 400 you -would write: - -base_criteria_values= { 1 => { ofv => 400 } }- -
Composite options
- -The composite options can not be specified on the command line. An -exception is the extra_data_files option -which is valid for all utilities. A composite option section starts -with an option header followed by a set of lines with a left side, an -equal sign and a right side.
- -[extra_data_files]
- sub.dta=ID,GRP,AGE,SEX,ARR,SHD,NYHA,LVEF,WT,HT,RACE,ALCO,SMOK,BETA
-
[test_relations]
- CL=AGE,SEX,ARR,SHD,NYHA,WT,RACE,ALCO,SMOK,BETA,\
- ALBU,BILI,AST,ALT,ALKP,POT,MAG,CA,NA,TOTP, \
- ANT1,CLIA,CLIB,CLIC,CL3,CIME,METF,PROC
- V=SEX,WT,ALBU,TOTP,LDIU,TDIU,ACOA,SULP
[included_relations]
- CL=TDIU-2,CLIA-2,SEX-2
- V=WT,ACOA-2,SEX-3,TOTP
-
[valid_states]
- categorical=1,2
- continuous=1,2,3
[code]
- CL:WT-1=THETA(1)
[code]
- CL:*-1=THETA(1)
[code]
- *:*-1=THETA(1)
- Generally it is useful to include the parameter and/or the - covariate in the code. So to make it possible when using - wildcards you can use the generic variables PARM and COV which - will be replaced with the parameter and covariate in question - for the current relation. - -
[lower_bounds]
- CL:WT-2=0.1, 0.05
[upper_bounds]
- CL:WT-2=0.3, 0.08
[inits]
- CL:WT-2=0.15,0.07
THETA(1) = 0.1,0.15,0.4
- THETA(2) = 0.05,0.07,0.08
-
-
|
- |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- |
Valid states for the parameter-covariate relations
+ +The SCM tool in PsN is written to be flexible in the shape of the +parameter-covariate relations. Currently there is a fixed set of +available forms of relations but there is ongoing development aiming +at full flexibility for the user with regard to relation-shape +definitions.
+ +The avaialable shapes or states for the +parameter-covariate relations for continuous covariates are (1) not +included, (2) included as a linear relation and (3) included as a +piece-wise linear relation with two slopes.
+ +Categorical covariates are either (1) not included or (2) included with an extra parameter added for each but the most common category.
+The figures, 1, 2 and 3, are used when specifying included relations below.
+ + +The syntax of the simple options is just the name of the option +followed by the equal sign and a valid value for the option. For +example:
+ +retries=5
+This states that a maximum of 5 retries will be used in the executions.
+Some options accept Perl code: +base_criteria_values={ ofv => -9571.234}
+Other take comma-separated lists: +continuous_covariates=AGE,WT,ALBU,BILI,AST,ALT,ALKP,POT,MAG,CA,NA,TOTP
+ +Some options don't accept a value on the command line. They set the +behavior of the utility simply by being specified or not. In the +configuration file these options need to be followed by 1 or a 0. A 1 +indicates that it is used and a 0 that it is not used. + +fix=1
+You can place a comment anywhere in the file by prefixing the line with a semicolon: +;ask_if_fail=0
+If an option is long you can break the line with a backslash, just a linebreak will not work: +categorical_covariates=SEX,ARR,SHD,NYHA,RACE,ALCO,SMOK,BETA,CGLY,LDIU,\
+ TDIU,CANT,ACE,NITR,ACOA,POTA,TWOC,TREA,TWOD,INDU,\
+ TUBS,ALQT,ANTP,ANTD,ANTM,ANTH,ANTB,SULP,ANT1,CLIA,\
+ CLIB,CLIC,CL3,CIME,METF,FENM,PROC,HEP1,HEP2,HEP3
Simple options
+ +The simple options are the SCM specific command line options and the +command line options common to all PsN Utilties. + +List options
+ +List options are options that take enumerations of values like the +categorical_covariates option: + +categorical_covariates=SEX,ARR,SHD,NYHA,RAC
+ +The list options valid in the configuration file are: + +
categorical_covariates
+ +The categorical_covariates list option is +neccessary for the scm to know which type of NONMEM code to generate +for the parameter covariate relation. + +continuous_covariates
+ +The categorical_covariates list option is +neccessary for the scm to know which type of NONMEM code to generate +for the parameter covariate relation. + +do_not_drop
+ +If the dataset used with the scm is to wide, scm will drop the data +columns that correponds to covariate which is not used in a particular +step. However, if you have used that covariate in code that is not +affected by the scm, NONMEM will produce an error. Therefore it is +neccessary for you to specify which those covariates are, using the +do_not_drop list option. + +extra_files
+ +If you need some extraordinary file to be copied into the NONMEM +execution directory, specify them with the extra_files list option. + +Code options
+ +Code options are almost like a Simple option. With the difference that +the right side is evaluted by the perl interpretor. If you don't +understand the difference, it is probably not important. However, it +is available for a reason. The SCM have hooks for custom goodness of +fit functions. Those functions may need some special input data. And +for flexibility, we allow that data to be just about anything, the +side effect is that it becomes to complex for the configuration file +structure. The solution is to allow options that are small Perl +programs. Those options we refer to as code options. + +base_criteria_values
+ +The base_criteria_values overrides default +criterias for the goodness of fit function used. The default goodness +of fit function takes its base_criteria_value to be the ofv of the +initial model. If you would like to change the base ofv to 400 you +would write: + +base_criteria_values= { ofv => 400 } }
+Composite options
+ +The composite options can not be specified on the command line. An +exception is the extra_data_files option +which is valid for all utilities. A composite option section starts +with an option header followed by a set of lines with a left side, an +equal sign and a right side.
+ +[extra_data_files]
+ sub.dta=ID,GRP,AGE,SEX,ARR,SHD,NYHA,LVEF,WT,HT,RACE,ALCO,SMOK,BETA
+
[test_relations]
+ CL=AGE,SEX,ARR,SHD,NYHA,WT,RACE,ALCO,SMOK,BETA,\
+ ALBU,BILI,AST,ALT,ALKP,POT,MAG,CA,NA,TOTP, \
+ ANT1,CLIA,CLIB,CLIC,CL3,CIME,METF,PROC
+ V=SEX,WT,ALBU,TOTP,LDIU,TDIU,ACOA,SULP
[included_relations]
+ CL=TDIU-2,CLIA-2,SEX-2
+ V=WT,ACOA-2,SEX-3,TOTP
+
[valid_states]
+ categorical=1,2
+ continuous=1,2,3
[code]
+ CL:WT-1=THETA(1)
[code]
+ CL:*-1=THETA(1)
[code]
+ *:*-1=THETA(1)
+ Generally it is useful to include the parameter and/or the + covariate in the code. So to make it possible when using + wildcards you can use the generic variables PARM and COV which + will be replaced with the parameter and covariate in question + for the current relation. + +
[lower_bounds]
+ CL:WT-2=0.1, 0.05
[upper_bounds]
+ CL:WT-2=0.3, 0.08
[inits]
+ CL:WT-2=0.15,0.07
THETA(1) = 0.1,0.15,0.4
+ THETA(2) = 0.05,0.07,0.08
+
+
|
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+ |
-retries='integer'
@@ -669,6 +675,15 @@ EOF -retries option is 6. EOF + $help_hash{-crash_restarts} = <<'EOF'; +-crash_restarts='integer'
+ + If a NONMEM outputfile is produced but PsN is unable to read it + properly it is assumed that NONMEM crashed, probably due to + something in the operating system, and PsN will start the run + again. But PsN will not consider it a retry and will not change + initial estimates. The default value is 4. +EOF $help_hash{-significant_digits_rerun} = <<'EOF';-significant_digits_rerun='number'
@@ -798,7 +813,10 @@ EOF close( EXAMPLES ); open(SYNOPSIS, '>', 'html/' . $command . '_synopsis.php' ); - print SYNOPSIS $help_hash{Pre_help_message} . "\t$command " . common_options::print_help($command,$required_options, $optional_options)."" ; + print SYNOPSIS $help_hash{Pre_help_message},"\n"; + print SYNOPSIS "
$command " . common_options::print_help($command,$required_options, $optional_options)."\n\n" ; close( SYNOPSIS ); open(OPTIONS, '>', 'html/' . $command . '_options.php' ); @@ -816,7 +834,7 @@ EOF if( exists $help_hash{'-'.$option}){ $opt_help .= $help_hash{'-'.$option}."\n\n"; } else { - $opt_help .= "
-$option
No help available for '$option'
"; + $opt_help .= "-$option
No help available for '$option'
"; } } print OPTIONS $help_hash{Options} . $opt_help; diff --git a/lib/data_subs.pm b/lib/data_subs.pm index eebb43c..042ccbe 100644 --- a/lib/data_subs.pm +++ b/lib/data_subs.pm @@ -725,7 +725,12 @@ start count_ind { # Returns the number of individuals in the data set. $self -> synchronize; - $num = scalar @{$self -> {'individuals'}}; + if( defined $self -> individuals() ) { + $num = scalar @{$self -> individuals()}; + } else { + debug -> die( message => "No individuals found in file ". + $self -> filename() ); + } } end count_ind @@ -1088,6 +1093,7 @@ start wrap if ( defined $self -> {'secondary_columns'} ); @primary_columns = @{$self -> {'primary_columns'}} if ( defined $self -> {'primary_columns'} ); + $self -> synced(0); } end wrap # }}} wrap diff --git a/lib/debug_subs.pm b/lib/debug_subs.pm index 8e2a17c..ac31504 100644 --- a/lib/debug_subs.pm +++ b/lib/debug_subs.pm @@ -48,8 +48,6 @@ start include statements use Carp; use Carp qw(cluck); use Text::Wrap; -use File::Find 'find'; -use File::Spec::Functions; # These variables are used for mapping level names to numbers. @@ -88,7 +86,6 @@ start level } else { return $the_instance -> {'level'}; } - #$self -> psn_in_inc; return; } end level @@ -236,13 +233,12 @@ start warn $subroutine. " : " . $message . "\n"; } else { my $level_name_length = length( $level_name ); - my $indent = ' ' x (4); - $text = "\n". $level_name . ': ' . $package . '->' . $subroutine. " :"; - $text .= wrap($prefix, $prefix . $indent, "\n" . $message ); - $text .= "\n"; + my $indent = ' ' x ($level_name_length + 4); + $text = wrap($prefix, $prefix . $indent, $level_name . ': ' . $package . '->' . + $subroutine. " : " . $message . "\n" ); } - if( $the_instance -> {'warn_with_trace'} ){ + if( $the_instance -> {'warn_with_trace'} >= $level ){ cluck( $text ); } else { print STDERR ( $text ); @@ -276,7 +272,7 @@ start die my $arr = scalar(@longmess); $prefix = ' ' x ($arr-2); } - if( $the_instance -> {'level'} > 1 ){ + if( $the_instance -> {'level'} > 0 ){ $! = 1; confess( $prefix . $message ); } else { @@ -287,15 +283,3 @@ start die } end die # }}} - -# {{{ psn_in_inc -start psn_in_inc -foreach my $plib ( @INC ) { - if ( $the_instance -> {'level'} > 1 ) { - find( { wanted => sub { print canonpath($_),"\n" if /PsN.*\.pm\z/ }, no_chdir => 1 }, $plib ) if ( $plib ne '.' ); - } elsif ( $the_instance -> {'level'} == 1 ) { - find( { wanted => sub { print canonpath($_),"\n" if /PsN\.pm\z/ }, no_chdir => 1 }, $plib ) if ( $plib ne '.' ); - } -} -end psn_in_inc -# }}} psn_in_inc diff --git a/lib/model/.cvsignore b/lib/model/.cvsignore index e4b6896..bb73cd5 100644 --- a/lib/model/.cvsignore +++ b/lib/model/.cvsignore @@ -1,2 +1,6 @@ +cwres_module.pm +iofv_module.pm +mirror_plot_module.pm +nonparametric_module.pm +shrinkage_module.pm problem.pm -k diff --git a/lib/model/cwres_module_subs.pm b/lib/model/cwres_module_subs.pm index 6de0aeb..d28cfac 100644 --- a/lib/model/cwres_module_subs.pm +++ b/lib/model/cwres_module_subs.pm @@ -7,6 +7,8 @@ start new $this -> {'nm_version'} = 'default'; } + my $mirror_name = $this -> {'mirror_plots'} ? 'sim' : ''; + my ($nmdir,$version) = split(/,/ , $PsN::config -> { 'nm_versions' } -> { $this -> {'nm_version'} } ); if( not defined $version ){ @@ -61,10 +63,22 @@ start new if( defined $sd_ref ) { foreach my $tabname ( @{$sd_ref} ) { if( $tabname =~ /[sd,pa]tab(\d+)/ ) { - $this -> sdno($1); + my $sdno = $1; + if( $sdno eq '' ){ + $sdno = 1; + } + $this -> sdno($sdno); for( my $i = 0; $i <= $#cwtab_names; $i++ ) { - if( $cwtab_names[$i] =~ /(\w+)\.(\d+)/ ) { - $cwtab_names[$i] = $1.$this -> sdno().'.'.$2; + + # This regular expression is probably quite unneccessary. It + # matches evertyhing before the first 'dot' in a filename, + # the dot, and the rest of the name(dots included). We can + # then inject a number before the first dot. It also handles + # no dots, the number will then be injected at the end of + # the filename. + + if( $cwtab_names[$i] =~ /([^\.]+)(\.{0,1})(.*)/ ) { + $cwtab_names[$i] = $1.$sdno.$mirror_name.$2.$3; } } $this -> cwtab_names( \@cwtab_names); @@ -114,10 +128,13 @@ start new # {{{ fortran code push( @{$code}, ('" IF (ICALL.EQ.0) THEN', - '"C open files here, if necessary') ); - for( my $i = 0; $i <= $#cwtab_names; $i++ ) { - push( @{$code}, '" OPEN(5'.$i.',FILE=\''.$cwtab_names[$i].'\')' ); - } + '"C open files here, if necessary', + '" OPEN(50,FILE=\'cwtab'.$this -> sdno().$mirror_name.'.est\')') ); + + #for( my $i = 0; $i <= $#cwtab_names; $i++ ) { + #push( @{$code}, '" OPEN(5'.$i.',FILE=\''.$cwtab_names[$i].'\')' ); + #} + push( @{$code}, # {{{ fortan code ('" ENDIF', @@ -125,6 +142,7 @@ start new '" MODE=0', '" CALL PASS(MODE)', '" MODE=1', + '" WRITE (50,*) \'ETAS\'', '" 20 CALL PASS(MODE)', '" IF (MODE.EQ.0) GO TO 30', '" IF (NEWIND.NE.2) THEN', @@ -133,16 +151,14 @@ start new '" ENDIF', '" GO TO 20', '" 30 CONTINUE', - '" WRITE (51,99) OBJECT', - '" WRITE (52,99) (THETAF(J),J=1,NTH)', - '" WRITE (53,99) (SETH(J), J=1,NTH)', + '" WRITE (50,*) \'THETAS\'', + '" WRITE (50,99) (THETAF(J),J=1,NTH)', + '" WRITE (50,*) \'OMEGAS\'', '" DO 7000 I=1,NETA', - '" WRITE (54,99) (OMEGAF(I,J),J=1,NETA)', - '" 7000 WRITE (55,99) (SEOM(I,J), J=1,NETA)', + '" 7000 WRITE (50,99) (OMEGAF(I,J),J=1,NETA)', + '" WRITE (50,*) \'SIGMAS\'', '" DO 7999 I=1,NEPS', - '" WRITE (56,99) (SIGMAF(I,J),J=1,NEPS)', - '" 7999 WRITE (57,99) (SESIG(I,J), J=1,NEPS)', - '" WRITE (58,98) IERE,IERC', + '" 7999 WRITE (50,99) (SIGMAF(I,J),J=1,NEPS)', '" ENDIF', '" 99 FORMAT (20E15.7)', '" 98 FORMAT (2I8)', @@ -153,60 +169,37 @@ start new } } elsif ( $version == 6 ) { + + my $code; + if( $have_advan ){ unless( $prob -> infns ){ $prob -> add_records( type => 'infn', record_strings => [] ); } - my $code = $prob -> infns -> [0] -> code; + $code = $prob -> infns -> [0] -> code; - push( @{$code}, 'IF (ICALL.EQ.3) THEN' ); - for( my $i = 0; $i <= $#cwtab_names; $i++ ) { - push( @{$code}, ' OPEN(5'.$i.',FILE=\''.$cwtab_names[$i].'\')' ); - } - push( @{$code}, - # {{{ fortran code - (' DO WHILE(DATA)', - ' IF (NEWIND.LE.1) WRITE (50,*) ETA', - ' ENDDO', - ' WRITE (51,*) OBJECT', - ' WRITE (52,*) THETA', - ' WRITE (53,*) SETHET', - ' WRITE (54,*) OMEGA(BLOCK)', - ' WRITE (55,*) SEOMEG(BLOCK)', - ' WRITE (56,*) SIGMA(BLOCK)', - ' WRITE (57,*) SESIGM(BLOCK)', - ' WRITE (58,*) IERE,IERC', - 'ENDIF') - - # }}} - ); } else { - my $code = $prob -> preds -> [0] -> code; - - push( @{$code}, 'IF (ICALL.EQ.3) THEN' ); - for( my $i = 0; $i <= $#cwtab_names; $i++ ) { - push( @{$code}, '" OPEN(5'.$i.',FILE=\''.$cwtab_names[$i].'\')' ); - } - push( @{$code}, - # {{{ fortran code - (' DO WHILE(DATA)', - ' IF (NEWIND.LE.1) WRITE (50,*) ETA', - ' ENDDO', - ' WRITE (51,*) OBJECT', - ' WRITE (52,*) THETA', - ' WRITE (53,*) SETHET', - ' WRITE (54,*) OMEGA(BLOCK)', - ' WRITE (55,*) SEOMEG(BLOCK)', - ' WRITE (56,*) SIGMA(BLOCK)', - ' WRITE (57,*) SESIGM(BLOCK)', - ' WRITE (58,*) IERE,IERC', - 'ENDIF') - # }}} - ); + $code = $prob -> preds -> [0] -> code; + } + + push( @{$code}, + 'IF (ICALL.EQ.3) THEN', + ' OPEN(50,FILE=\'cwtab'.$this -> sdno().$mirror_name.'.est\')', + ' WRITE (50,*) \'ETAS\'', + ' DO WHILE(DATA)', + ' IF (NEWIND.LE.1) WRITE (50,*) ETA', + ' ENDDO', + ' WRITE (50,*) \'THETAS\'', + ' WRITE (50,*) THETA', + ' WRITE (50,*) \'OMEGAS\'', + ' WRITE (50,*) OMEGA(BLOCK)', + ' WRITE (50,*) \'SIGMAS\'', + ' WRITE (50,*) SIGMA(BLOCK)', + 'ENDIF' ); } @@ -269,12 +262,12 @@ start new record_strings => ['ID ', join(' ',@table_row), "IPRED DV $mdv NOPRINT ". - "ONEHEADER FILE=cwtab".$this -> sdno()] ); - $prob -> add_records( type => 'table', - record_strings => ['ID ', - join(' ',@table_row), - "IPRED DV $mdv NOPRINT ". - "ONEHEADER FILE=cwtab".$this -> sdno().'.cwres'] ); + "ONEHEADER FILE=cwtab".$this -> sdno().'.deriv'] ); +# $prob -> add_records( type => 'table', +# record_strings => ['ID ', +# join(' ',@table_row), +# "IPRED DV $mdv NOPRINT ". +# "ONEHEADER FILE=cwtab".$this -> sdno().'.cwres'] ); } end new @@ -287,7 +280,8 @@ start post_process my ($advan,$junk) = $self -> {'problem'} -> _option_val_pos( record_name => 'subroutine', name => 'ADVAN', exact_match => 0); - my @cwtab_names = @{$self -> cwtab_names}; + + my $mirror_name = $self -> {'mirror_plots'} ? 'sim' : ''; if( $self -> {'nm_version'} == 5 and scalar(@{$advan}) > 0 ){ @@ -318,16 +312,19 @@ EOF print INFN " DATA NTH,NETA,NEPS/$ntheta,$neta,$neps/\n"; print INFN " IF (ICALL.EQ.0) THEN\nC open files here, if necessary\n"; - for( my $i = 0; $i <= $#cwtab_names; $i++ ) { - print INFN ' OPEN(5'.$i.',FILE=\''.$cwtab_names[$i].'\')'."\n"; - } - + print INFN " OPEN(50,FILE='cwtab".$self -> sdno().$mirror_name.".est')\n"; + +# for( my $i = 0; $i <= $#cwtab_names; $i++ ) { +# print INFN ' OPEN(5'.$i.',FILE=\''.$cwtab_names[$i].'\')'."\n"; +# } + print INFN << "EOF"; ENDIF IF (ICALL.EQ.3) THEN MODE=0 CALL PASS(MODE) MODE=1 + WRITE (50,*) 'ETAS' 20 CALL PASS(MODE) IF (MODE.EQ.0) GO TO 30 IF (NEWIND.NE.2) THEN @@ -336,16 +333,14 @@ EOF ENDIF GO TO 20 30 CONTINUE - WRITE (51,99) OBJECT - WRITE (52,99) (THETAF(J),J=1,NTH) - WRITE (53,99) (SETH(J), J=1,NTH) + WRITE (50,*) 'THETAS' + WRITE (50,99) (THETAF(J),J=1,NTH) + WRITE (50,*) 'OMEGAS' DO 7000 I=1,NETA - WRITE (54,99) (OMEGAF(I,J),J=1,NETA) - 7000 WRITE (55,99) (SEOM(I,J), J=1,NETA) + 7000 WRITE (50,99) (OMEGAF(I,J),J=1,NETA) + WRITE (50,*) 'SIGMAS' DO 7999 I=1,NEPS - WRITE (56,99) (SIGMAF(I,J),J=1,NEPS) - 7999 WRITE (57,99) (SESIG(I,J), J=1,NEPS) - WRITE (58,98) IERE,IERC + 7999 WRITE (50,99) (SIGMAF(I,J),J=1,NEPS) ENDIF 99 FORMAT (20E15.7) 98 FORMAT (2I8) diff --git a/lib/model/problem/error_subs.pm b/lib/model/problem/error_subs.pm index e2f91a6..cb10c04 100644 --- a/lib/model/problem/error_subs.pm +++ b/lib/model/problem/error_subs.pm @@ -1,2 +1,47 @@ start new end new + +start _format_record + { + if ( defined $self -> {'verbatim_first'} + or defined $self -> {'code'} + or defined $self -> {'verbatim_last'} ) { + my @class_names = split('::',ref($self)); + my $fname = uc(pop(@class_names)); + @formatted = "\$".$fname; + } + if ( defined $self -> {'verbatim_first'} ) { + push( @formatted, '"FIRST' ); + push( @formatted, @{$self -> {'verbatim_first'}} ); + } + my @cont; + if ( defined $self -> {'secondary_columns'} ) { + for ( my $i = 0; $i < scalar @{$self -> {'secondary_columns'}}; $i++ ) { + my $k = 1; + for ( my $j = 0; $j < scalar @{$self -> {'secondary_columns'}[$i]}; $j++ ) { + if ( $self -> {'secondary_columns'}[$i][$j][0] eq 'ID' or + $self -> {'secondary_columns'}[$i][$j][0] eq 'CONT' ) { + $k++; + next; + } + next if ( $self -> {'secondary_columns'}[$i][$j][0] =~ /XX(\d+)/ ); + my $str = "\" ".$self -> {'secondary_columns'}[$i][$j][0].'1 = EVTREC('.($i+1). + ','.($k++).")\n"; + $str = $str.$self -> {'secondary_columns'}[$i][$j][0].' = '. + $self -> {'secondary_columns'}[$i][$j][0].'1'."\n"; + push( @cont, $str ); + } + } + } + + push( @formatted, @cont ); + if ( defined $self -> {'code'} ) { + push( @formatted, @{$self -> {'code'}} ); + } + if ( defined $self -> {'verbatim_last'} ) { + push( @formatted, '"LAST' ); + push( @formatted, @{$self -> {'verbatim_last'}} ); + } + } +end _format_record + diff --git a/lib/model/problem/record_subs.pm b/lib/model/problem/record_subs.pm index e5d06ca..e761ba5 100644 --- a/lib/model/problem/record_subs.pm +++ b/lib/model/problem/record_subs.pm @@ -32,9 +32,11 @@ start remove_option my @options = @{$self -> {'options'}}; my @new_options = (); foreach my $option ( @options ) { - if ( $option -> name ne $name ) { - push( @new_options, $option ); - } + next if ( $option -> name eq $name ); + + next if ( $fuzzy_match and index( $name, $option -> name ) > -1 ); + + push( @new_options, $option ); } $self -> {'options'} = \@new_options; diff --git a/lib/model/problem_subs.pm b/lib/model/problem_subs.pm index d7366b5..f037123 100644 --- a/lib/model/problem_subs.pm +++ b/lib/model/problem_subs.pm @@ -44,10 +44,11 @@ start new $this -> {'ignore_missing_files'} ); } - if( $this -> {'compute_cwres'} ){ + if( $this -> {'cwres'} ){ $this -> add_cwres_module( 'init_data' => { problem => $this, - nm_version => $this -> {'nm_version'} } ); + nm_version => $this -> {'nm_version'}, + mirror_plots => $this -> {'mirror_plots'} } ); } @@ -191,7 +192,7 @@ start drop_dropped my @options = @{$opt_ref}; my @keep; foreach my $option ( @options ) { - push ( @keep, $option ) if ( not $option -> value eq 'DROP' or $option -> value eq 'SKIP' or + push ( @keep, $option ) if ( not ($option -> value eq 'DROP' or $option -> value eq 'SKIP') or $option -> name =~ /DAT(E|1|2|3)/ ); } $input -> options( \@keep ); @@ -349,13 +350,30 @@ start indexes my $accessor = $parameter_type.'s'; if( defined $self -> {$accessor} ){ + + # If we hit a "SAME" parameter we need to remember the + # previous parameter size. ( calculated as "row - previous_row" ) + + my $previous_row = 0; + foreach my $record ( @{$self -> $accessor} ) { # If not a block or if the block is of size 1 use normal numbering - if ( ( ! defined $record -> size ) or - ( $record -> size < 2 )) { - if( $record -> same() ) { - push( @indexes, $row++ ); - } elsif ( defined $record -> options ) { + + if( $record -> same ) { + + if( $previous_row == 0 ){ + 'debug' -> die( message => "You can't have an $parameter_type estimate defined as SAME if it's the first estimate" ); + } + my $size = $row - $previous_row; + $previous_row = $row; + for( 1..$size ){ + push( @indexes, $row++); + } + + } elsif ( ( ! defined $record -> size ) or + ( $record -> size < 2 )) { + if ( defined $record -> options ) { + $previous_row = $row; foreach my $option ( @{$record -> options} ) { push( @indexes, $row++ ); } @@ -372,6 +390,7 @@ start indexes } } } + $previous_row = $row; $row += $size; } } @@ -402,7 +421,18 @@ start nomegas foreach my $omega ( @{$self -> {'omegas'}} ) { my $size = $omega -> size; if( defined $size ) { - $nomegas += $size; + + # If the record has a size, it is of block form with diagonal of + # length given by $size. The actual values in the model file is + # then the arithmetic sum: (n*(n+1))/2 + + if( $with_correlations ){ + $nomegas += ($size*($size+1))/2; + + # But we really only want the diagonal elements here: + } else { + $nomegas += $size; + } } else { $nomegas += scalar @{$omega -> options}; } @@ -419,7 +449,21 @@ start nsigmas foreach my $sigma ( @{$self -> {'sigmas'}} ) { my $size = $sigma -> size; if( defined $size ) { - $nsigmas += $size; + + # If the record has a size, it is of block form with diagonal of + # length given by $size. The actual values in the model file is + # then the arithmetic sum: (n*(n+1))/2 + + if( $with_correlations ){ + + $nsigmas += ($size*($size+1))/2; + + } else { + + # But we really only want the diagonal elements here: + + $nsigmas += $size; + } } else { $nsigmas += scalar @{$sigma -> options}; } @@ -476,9 +520,13 @@ start secondary_columns if ( defined $parm ) { if ( defined $self -> pks ) { $self -> pks -> [0] -> secondary_columns($parm); - } else { + } + if ( defined $self -> preds ) { $self -> preds -> [0] -> secondary_columns($parm); } + if ( defined $self -> errors ) { + $self -> errors -> [0] -> secondary_columns($parm); + } # This is a lengthy bit of code to create a reasonable header and secondary # columns for the table files. When the data file of the problem is wrapped # using the CONT data item, the rows of the table files will be duplicated (or @@ -651,7 +699,7 @@ if( defined $self -> {$accessor} ) { record_strings => ["$option_name=$option_value"] ); } else { 'debug' -> warn( level => 2, - message => "No records of typ $accessor and add_option ". + message => "No records of type $accessor and add_option ". "set not to add one" ); } } @@ -671,11 +719,12 @@ unless( $self -> can($accessor) ){ if( defined $self -> {$accessor} ) { my @records = @{$self -> {$accessor}}; foreach my $record ( @records ) { - $record -> remove_option( name => $option_name ); + $record -> remove_option( name => $option_name, + fuzzy_match => $fuzzy_match ); } } else { 'debug' -> warn( level => 2, - message => "No records of typ $accessor" ); + message => "No records of type $accessor" ); } end remove_option @@ -811,7 +860,8 @@ start _init_attr if ( $record -> same() ) { # SAME == true: Nothing to be done. Just move forward to next $OMEGA but # increase counter first - $opt_num += $prev_size*($prev_size+1)/2; + + $opt_num += $prev_size; } else { foreach my $option ( @{$record -> options} ) { if ( scalar @parameter_numbers > 0 ) { @@ -821,6 +871,9 @@ start _init_attr if ( $attribute eq 'init' ) { push( @diagnostics, $option -> check_and_set_init( new_value => $num_val{$num} ) ); + } elsif( $attribute eq 'fix' and defined $record -> size() ){ + # size() tells us this is a block and we must fix on record level. + $record -> fix( $num_val{$num} ); } else { $option -> $attribute( $num_val{$num} ); } @@ -830,42 +883,66 @@ start _init_attr if ( $attribute eq 'init' ) { push( @diagnostics, $option -> check_and_set_init( new_value => shift( @new_values ) ) ); + } elsif( $attribute eq 'fix' and defined $record -> size() ){ + # size() tells us this is a block and we must fix on record level. + $record -> fix( shift( @new_values ) ); } else { $option -> $attribute( shift( @new_values ) ); } } $opt_num++; } - $prev_size = $record -> size; + if( $parameter_type eq 'theta' ){ + $prev_size = scalar @{$record -> options}; + } else { + my $size = $record -> size; + if( defined $size ) { + $prev_size = ($size*($size+1))/2; + } else { + $prev_size = scalar @{$record -> options}; + } + } } } # If $add_if_absent is set, any parameters that were not found above are # added below: + my @nums = sort {$a<=>$b} keys %found; + my $new_record = "model::problem::$parameter_type" -> new(); + my $do_add_record; foreach my $num ( @nums ) { if ( $add_if_absent and not $found{$num} ) { + $do_add_record = 1; unless($num == $opt_num) { 'debug' -> die( message => "Attempt to add a parameter with higher number ($num) than the number\n". "of parameters + 1 ($opt_num)\n" ); } # Get the last record of $parameter_type - my $last_record = $records[$#records]; + # my $new_record = $records[$#records]; my $option_class; if( $parameter_type eq 'theta' ){ $option_class = 'model::problem::record::theta_option'; } else { $option_class = 'model::problem::record::init_option'; } -# print "NUM: $num did not find: ",$found{$num},"\n"; + # Push a new option to this last record my $option = $option_class -> new; if ( $attribute eq 'init' ) { $option -> check_and_set_init( new_value => $num_val{$num} ); + } elsif( $attribute eq 'fix' and defined $new_record -> size() ){ + + # size() tells us this is a block and we must fix on + # record level. This will never happen, as we can't + # add BLOCKS, at least not like this. + + $new_record -> fix( $num_val{$num} ); } else { $option -> $attribute( $num_val{$num} ); } - push( @{$last_record -> {'options'}}, $option ); + push( @{$new_record -> {'options'}}, $option ); + # So we've added a parameter. Possible to add more, # lets increase the highest found: $opt_num++; @@ -877,6 +954,11 @@ start _init_attr @parameter_values = @diagnostics; } + if( $do_add_record ){ + push( @records, $new_record ); + $self -> {$accessor} = \@records ; + } + # }}} Update values } else { # {{{ Retrieve values @@ -1108,7 +1190,7 @@ start _option_val_pos @records = @{$self -> {$accessor}} ; } else { 'debug' -> warn( level => 2, - message => "No records of typ $accessor" ); + message => "No records of type $accessor" ); @records = (); } my @options = (); diff --git a/lib/model_subs.pm b/lib/model_subs.pm index 1a8df48..6e6e157 100644 --- a/lib/model_subs.pm +++ b/lib/model_subs.pm @@ -215,6 +215,25 @@ start new target => $this -> {'target'}, model_id => $this -> {'model_id'} ) ); } + + # Adding mirror_plots module here, since it can add + # $PROBLEMS. Also it needs to know wheter an lst file exists + # or not. + + if( $this -> {'mirror_plots'} > 0 ){ + my $mirror_plot_module = model::mirror_plot_module -> new( base_model => $this, + nr_of_mirrors => $this -> {'mirror_plots'}, + cwres => $this -> {'cwres'}, + mirror_from_lst => $this -> {'mirror_from_lst'}); + push( @{$this -> {'mirror_plot_modules'}}, $mirror_plot_module ); + } + + if( $this -> {'iofv'} > 0 ){ + my $iofv_module = model::iofv_module -> new( base_model => $this, + nm_version => $this -> {'nm_version'}); + push( @{$this -> {'iofv_modules'}}, $iofv_module ); + } + } end new @@ -738,7 +757,7 @@ start set_records $problems[$i-1] -> set_records( 'type' => $type, 'record_strings' => \@record_strings ); } else { - 'debug' -> die( "Problem number $i does not exist." ); + 'debug' -> die( message => "Problem number $i does not exist." ); } } # else { @@ -1175,7 +1194,7 @@ start datas my @new_datas = @{$parm}; # Check that new_headers and problems match 'debug' -> die( message => "The number of problems $nprobs and". - " new data ". $#new_datas+1 ." don't match in ". + " new data ". ($#new_datas+1) ." don't match in ". $self -> full_name ) unless ( $#new_datas + 1 == $nprobs ); if ( defined $self -> {'problems'} ) { for( my $i = 0; $i < $nprobs; $i++ ) { @@ -2345,6 +2364,11 @@ start is_option_set } foreach my $option ( @options ) { $found = 1 if ( defined $option and $option -> name eq $name ); + if( $fuzzy_match ){ + if( index( $name, $option -> name ) > -1 ){ + $found = 1; + } + } } } end is_option_set @@ -2669,6 +2693,7 @@ start labels @index = @{$self -> indexes( parameter_type => $parameter_type, parameter_numbers => \@parameter_numbers, problem_numbers => \@problem_numbers )}; + for ( my $i = 0; $i <= $#labels; $i++ ) { for ( my $j = 0; $j < scalar @{$labels[$i]}; $j++ ) { $idx = $index[$i][$j]; @@ -3035,7 +3060,6 @@ end min # {{{ name_val - =head2 fractions Usage: @@ -3338,7 +3362,7 @@ start nomegas my @problems = @{$self -> {'problems'}}; foreach my $i ( @problem_numbers ) { if ( defined $problems[ $i-1 ] ) { - push( @nomegas, $problems[ $i-1 ] -> nomegas ); + push( @nomegas, $problems[ $i-1 ] -> nomegas( with_correlations => $with_correlations )); } else { 'debug' -> die( "Problem number $i does not exist." ); } @@ -3407,7 +3431,7 @@ unless( $#problem_numbers >= 0 ){ my @problems = @{$self -> {'problems'}}; foreach my $i ( @problem_numbers ) { if ( defined $problems[ $i-1 ] ) { - push( @nsigmas, $problems[ $i-1 ] -> nsigmas ); + push( @nsigmas, $problems[ $i-1 ] -> nsigmas( with_correlations => $with_correlations )); } else { 'debug' -> die( "Problem number $i does not exist." ); } @@ -4371,7 +4395,21 @@ my ( $name_ref, $junk ) = $self -> record_name => 'estimation', problem_numbers => \@problem_numbers, new_values => \@new_names ); -@names = @{$name_ref}; + + +my ( $nonp_name_ref, $junk ) = $self -> + _option_val_pos( name => 'MSFO', + record_name => 'nonparametric', + problem_numbers => \@problem_numbers, + new_values => \@new_names ); + +if( length( @{$name_ref} > 0 ) ){ + push( @names, @{$name_ref} ); +} + +if( length( @{$nonp_name_ref} ) ){ + push( @names, @{$nonp_name_ref} ); +} end msfo_names @@ -4817,7 +4855,7 @@ start update_inits # } # }}} - + for ( my $i = 0; $i <= $#own_labels; $i++ ) { if( $from_output -> have_user_defined_prior ){ @@ -5055,6 +5093,8 @@ start wrap_data { my $default_wrap = 18; + $self -> drop_dropped(1); + my ( @wrap_columns, @cont_columns ); if ( not defined $wrap_column ) { for( my $i = 0; $i < scalar @{$self -> {'problems'}}; $i++ ) { @@ -5295,6 +5335,11 @@ start _write $data -> _write; } } + + if( $self -> {'iofv_modules'} ){ + $self -> {'iofv_modules'} -> [0] -> post_process; + } + } end _write @@ -5632,14 +5677,15 @@ start _read_problems ignore_missing_files => $self -> {'ignore_missing_files'}, ignore_missing_output_files => $self -> {'ignore_missing_output_files'}, sde => $self -> {'sde'}, - compute_cwres => $self -> {'compute_cwres'}, + cwres => $self -> {'cwres'}, + mirror_plots => $self -> {'mirror_plots'}, nm_version => $self -> {'nm_version'}, prob_arr => \@problem_lines, extra_data_file_name => $extra_data_files[$prob_num], extra_data_header => $extra_data_headers[$prob_num], shrinkage_module => $sh_mod ); push( @problems, $prob ); - if ( $self -> compute_cwres() ) { + if ( $self -> cwres() ) { my @eo; if ( defined $self -> extra_output() ) { @eo = @{$self -> extra_output()}; @@ -5677,9 +5723,11 @@ foreach my $i ( @problem_numbers ) { if ( defined $problems[ $i-1 ] ) { my $found = $self -> is_option_set( 'problem_number' => $i, 'record' => $record_name, - 'name' => $option_name ); + 'name' => $option_name, + 'fuzzy_match' => $fuzzy_match ); $problems[$i-1] -> remove_option( record_name => $record_name, - option_name => $option_name ) if ( $found ); + option_name => $option_name, + fuzzy_match => $fuzzy_match ) if ( $found ); $problems[$i-1] -> add_option( record_name => $record_name, option_name => $option_name, option_value => $option_value ); @@ -5724,7 +5772,8 @@ my @problems = @{$self -> {'problems'}}; foreach my $i ( @problem_numbers ) { if ( defined $problems[ $i-1 ] ) { $problems[$i-1] -> remove_option( record_name => $record_name, - option_name => $option_name ); + option_name => $option_name, + fuzzy_match => $fuzzy_match); } } @@ -5817,7 +5866,10 @@ start subroutine_files } } } - + + # BUG , nonmem6 might not require the file to be named .f And I've + # seen examples of files named .txt + @fsubs = keys %fsubs; if( @fsubs > 0 ){ for( my $i = 0; $i <= $#fsubs; $i ++ ){ diff --git a/lib/nonmem_subs.pm b/lib/nonmem_subs.pm index 244080a..3599114 100644 --- a/lib/nonmem_subs.pm +++ b/lib/nonmem_subs.pm @@ -50,7 +50,6 @@ start new unless( defined $nmdir ){ print "Unknown NONMEM version ",$this -> {'version'}," specified.\n"; - print "Configuration file is ",$PsN::config_file,"\n"; my @nmkeys = keys %{$PsN::config -> { 'nm_versions' }}; if ( $#nmkeys == 0 and defined $nmkeys[0] and @@ -125,29 +124,27 @@ start compile } my $modelfile = $self -> {'modelfile'}; + if( $Config{osname} eq 'MSWin32' ){ run3( "$nmdir/tr/nmtran.exe", $modelfile, \$self -> {'nmtran_message'}, \$self -> {'nmtran_message'} ); } else { run3( 'nice -' . $self -> {'nice'} . " $nmdir/tr/nmtran.exe", $modelfile, \$self -> {'nmtran_message'}, \$self -> {'nmtran_message'} ); } - #$self -> {'nmtran_message'} = `nice -19 $nmdir/tr/nmtran.exe < $modelfile 2>&1`; - open( NMMSG, '>compilation_output.txt' ); print( NMMSG $self -> {'nmtran_message'}, "\n" ); - + unless(-e 'FREPORT'){ close(NMMSG); $self -> {'error_message'} = "NMtran failed: \n" . $self -> {'nmtran_message'} ; return 0; } - + my $nmlink_message; - run3( "$nmlink", undef, \$nmlink_message, \$nmlink_message ); print( NMMSG $nmlink_message, "\n" ); - + my $fsub; if(-e 'FSUBS'){ @@ -160,7 +157,7 @@ start compile } } - if( defined $self -> {'fsubs'} ){ + if( defined $self -> {'fsubs'} and $self -> {'version'} != 6 ){ foreach my $sub ( @{$self -> {'fsubs'}} ){ $fsub .= " $sub"; } @@ -179,33 +176,37 @@ start compile my $compile_message; my $compile_command; + my @nmlib; + + if( $Config{osname} eq 'MSWin32' ){ + @nmlib = ("$nm\\NONMEM.obj","$nm\\BLKDAT.obj","$nm\\nonmem.lib"); + } else { + @nmlib = ("$nm/NONMEM.o", "$nm/BLKDAT.o", "$nm/nonmem.a"); + } + $compile_command = "g77 " . $self -> {'compiler_options'} . " -ononmem$version$adaptive $includes $fsub @link @nmlib 2>&1"; + if( $self -> {'compiler'} eq 'g77' ){ - my @nmlib = ("$nm/NONMEM.o", "$nm/BLKDAT.o", "$nm/nonmem.a"); $compile_command = "g77 " . $self -> {'compiler_options'} . " -ononmem$version$adaptive $includes $fsub @link @nmlib 2>&1"; } elsif( $self -> {'compiler'} eq 'df' or $self -> {'compiler'} eq 'fl32' ){ - - my @nmlib = ("$nm\\nonmem.obj", "$nm\\blkdat.obj", "$nm\\nonmem.lib"); $compile_command = $self -> {'compiler'}." " . $self -> {'compiler_options'} . " /Fenonmem $fsub @nmlib @link"; - + } elsif( $self -> {'compiler'} eq 'ifort' ){ - my @nmlib = ("$nm/NONMEM.o", "$nm/BLKDAT.o", "$nm/nonmem.a"); - $compile_command = "ifort " . $self -> {'compiler_options'} . " -ononmem$version$adaptive $includes $fsub @link @nmlib 2>&1"; + + $compile_command = "ifort " . $self -> {'compiler_options'} . " -ononmem$version$adaptive $includes $fsub @link @nmlib 2>&1"; + } run3( "$compile_command", undef, \$compile_message, \$compile_message ); print( NMMSG $compile_message, "\n" ); - + + close( NMMSG ); unless(-e "nonmem.exe" or -e "nonmem$version$adaptive" ) { $self -> {'error_message'} = "Fortran Compilation failed: \n" . $compile_message ; - close( NMMSG ); return 0; - } else { - print( NMMSG "Compilation done\n" ); - close( NMMSG ); } } end compile @@ -249,7 +250,7 @@ start execute } run3( "nice -n " . $self -> {'nice'} . " ./nonmem$version$adaptive", "FCON", $outputfile ); if ( -e "/proc/self/lock" ) { - open (OUTFILE,">/proc/self/lock") || die "Could not lock myself!\n"; + open (OUTFILE,">/proc/self/lock") || die "Could not unlock myself!\n"; print OUTFILE "1"; close (OUTFILE); } diff --git a/lib/output/problem/subproblem_subs.pm b/lib/output/problem/subproblem_subs.pm index 3a4674d..9144f52 100644 --- a/lib/output/problem/subproblem_subs.pm +++ b/lib/output/problem/subproblem_subs.pm @@ -196,7 +196,14 @@ start _compute_comegas_or_csigmas # undefined). my $row_size = 1; for( my $i = 0; $i <= $#raw_omegas_or_sigmas; $i+=$row_size ){ - my $omega_or_sigma_value = sqrt( $raw_omegas_or_sigmas[$i] ); + my $omega_or_sigma_value = undef; + if( $raw_omegas_or_sigmas[$i] >= 0 ) { + $omega_or_sigma_value = sqrt( $raw_omegas_or_sigmas[$i] ); + } else { + ui -> print( category => 'all', + message => "Warning: cannot take the square root of ". + "$omega_or_sigma with value ".$raw_omegas_or_sigmas[$i] ); + } push( @{$self -> {'c' . $omega_or_sigma .'s'}}, $omega_or_sigma_value ); $row_size ++; } diff --git a/lib/output/problem_subs.pm b/lib/output/problem_subs.pm index 94d5c57..90cfc91 100644 --- a/lib/output/problem_subs.pm +++ b/lib/output/problem_subs.pm @@ -491,7 +491,7 @@ while( $_ = @{$self -> {'lstfile'}}[ $start_pos++ ] ) { } } -unless( ( $self -> estimation_step_run() * $est_allowed ) or +unless( ( $self -> estimation_step_initiated() * $est_allowed ) or ( $self -> covariance_step_run() * $cov_allowed ) or ( $self -> nonparametric_step_run() * $nonp_allowed ) or ( $self -> tables_step_run() * $tables_allowed ) ) { @@ -617,20 +617,24 @@ while( $_ = @{$self -> {'lstfile'}}[ $start_pos++ ] ) { if ( /^0COVARIANCE STEP OMITTED/ or /0TABLES STEP OMITTED/ or /1DOUBLE PRECISION PREDPP/ or - /0SEARCH WITH ESTIMATION STEP WILL NOT PROCEED/ ) { + /0SEARCH WITH ESTIMATION STEP WILL NOT PROCEED/ or + /^1/ or + /^0MINIMIZATION/ or + /^ PROBLEM NO\.:\s+\d/ ) { # This is ok, the nonp step was not used. last; } - if( /^ PROBLEM NO\.:\s+\d/ or - /^0MINIMIZATION/ ) { + +# if( /^ PROBLEM NO\.:\s+\d/ or +# /^0MINIMIZATION/ ) { # This should not happen, raise error - my $errmess = "Found $_ while searching for the (optional) ". - "nonparametric step indicator\n"; - debug -> warn( level => 1, - message => $errmess."$!" ); - $self -> parsing_error( message => $errmess."$!" ); - return; - } +# my $errmess = "Found $_ while searching for the (optional) ". +# "nonparametric step indicator\n"; +# debug -> warn( level => 1, +# message => $errmess."$!" ); +# $self -> parsing_error( message => $errmess."$!" ); +# return; +# } if ( ($start_pos + 1) == scalar @{$self -> {'lstfile'}} ) { #EOF This should not happen, raise error @@ -754,7 +758,6 @@ start _read_inits my $start_pos = $self -> {'lstfile_pos'}; my ( @thetas, @omegas, @sigmas ); my $thetarea = 0; - my $thetabounds = 0; my $omegarea = 0; my $sigmarea = 0; my $success = 0; @@ -808,10 +811,6 @@ start _read_inits $thetarea = 1; } - if ( $thetarea and /LOWER BOUND\s+INITIAL EST\s+UPPER BOUND/ ){ - $thetabounds = 1; - } - if ( /^0ESTIMATION STEP OMITTED/ or /^0SIMULATION STEP OMITTED/ ) { # We want to find this if we are currently reading the omega or sigma inits @@ -829,25 +828,16 @@ start _read_inits return; } if ( $thetarea and /^\s*-?\d*\.\d*/ ) { - if( $thetabounds ){ - my @T = split(' ',$_); - push(@{$self -> {'initthetas'}},eval($T[1])); - push(@{$self -> {'lower_theta_bounds'}},eval($T[0])); - push(@{$self -> {'upper_theta_bounds'}},eval($T[2])); - if ( $T[0] == $T[1] and $T[0] == $T[2] ) { - push(@{$self -> {'fixedthetas'}},1); - push(@{$self -> {'estimated_thetas'}},0); - } else { - push(@{$self -> {'fixedthetas'}},0); - push(@{$self -> {'estimated_thetas'}},1); - } + my @T = split(' ',$_); + push(@{$self -> {'initthetas'}},eval($T[1])); + push(@{$self -> {'lower_theta_bounds'}},eval($T[0])); + push(@{$self -> {'upper_theta_bounds'}},eval($T[2])); + if ( $T[0] == $T[1] and $T[0] == $T[2] ) { + push(@{$self -> {'fixedthetas'}},1); + push(@{$self -> {'estimated_thetas'}},0); } else { - my @T = split(' ',$_); - foreach my $theta( @T ){ - push( @{$self -> {'initthetas'}}, eval($theta)); - push(@{$self -> {'fixedthetas'}},0); - push(@{$self -> {'estimated_thetas'}},1); - } + push(@{$self -> {'fixedthetas'}},0); + push(@{$self -> {'estimated_thetas'}},1); } } if ( /^0INITIAL ESTIMATE OF OMEGA:/ ) { @@ -884,6 +874,7 @@ start _read_inits my $om_row = 1; while( ($start_pos + 1) < scalar @{$self -> {'lstfile'}} ) { if( $self -> {'lstfile'}[ $start_pos ] =~ /^0INITIAL ESTIMATE OF SIGMA/ or + $self -> {'lstfile'}[ $start_pos ] =~ /^0SIMULATION STEP OMITTED/ or $self -> {'lstfile'}[ $start_pos ] =~ /^0ESTIMATION STEP OMITTED/ or $self -> {'lstfile'}[ $start_pos ] =~ /^0OMEGA CONSTRAINED TO BE THIS INITIAL ESTIMATE/ ) { $start_pos--; @@ -892,7 +883,7 @@ start _read_inits # After ten rows of omegas NONMEM starts wrapping # lines. We then need to skip the first part of the - # wrapped lines. This nice little formula calculates + # wrapped lines. This nice littel formula calculates # how many lines to skip. my $skip_lines = ($om_row - $om_row % 10)/10; @@ -963,7 +954,7 @@ start _read_inits # After ten rows of sigmas NONMEM starts wrapping # lines. We then need to skip the first part of the - # wrapped lines. This nice little formula calculates + # wrapped lines. This nice littel formula calculates # how many lines to skip. my $skip_lines = ($sm_row - $sm_row % 10)/10; diff --git a/lib/output_subs.pm b/lib/output_subs.pm index 2966d31..cf3eb74 100644 --- a/lib/output_subs.pm +++ b/lib/output_subs.pm @@ -77,6 +77,8 @@ start new # be left on disk in an effort to preserve memory. The file # will be read if needed. + debug -> warn( level => 2, + message => "Initiating new\tNM::output object from file $parm{'filename'}" ); if ( defined $this -> {'filename'} and $this -> {'filename'} ne '' ) { ( $this -> {'directory'}, $this -> {'filename'} ) = OSspecific::absolute_path( $this -> {'directory'},$this->{'filename'} ); @@ -91,19 +93,7 @@ start new } } else { debug -> die( message => "No filename specified or filename equals empty string!" ); - } - if( defined $this -> problems() ) { - my $mes = $this -> parsing_error_message(); - foreach my $prob ( @{$this -> problems()} ) { - $mes .= $prob -> parsing_error_message(); - $this -> parsed_successfully($this -> parsed_successfully() * - $prob -> parsed_successfully()); - } - $this -> parsing_error_message( $mes ); - } - if( defined $this -> parsing_error_message() and - $this -> parsing_error_message() ne '' ) { - print $this -> full_name,":\n",$this -> parsing_error_message(); + $this->{'filename'} = 'tempfile'; } if( defined $this -> problems() ) { my $mes = $this -> parsing_error_message(); @@ -739,7 +729,7 @@ start _read_problems $self -> {'lstfile_pos'} = 0; -# {{{ Old db code. Keep for now +# Old db code. Keep for now # if ( $PsN::config -> {'_'} -> {'use_database'} and # $self -> {'register_in_database'} and # defined $self -> {'output_id'} ) { @@ -758,7 +748,6 @@ start _read_problems # $dbh -> disconnect; # } -# }}} my $problem_start; my $success = 0; @@ -1141,6 +1130,7 @@ start flush { $self -> {'problems'} = undef; + $self -> {'synced'} = 0; } end flush # }}} flush diff --git a/lib/psn.conf b/lib/psn.conf index 0ea7c61..6dbe76e 100644 --- a/lib/psn.conf +++ b/lib/psn.conf @@ -19,20 +19,21 @@ output_style = SPLUS ; enables automatic calculation of conditional weighted residuals ; (CWRES). This feature requires that Xpose version 4.0 preview ; release 5 is also installed. -;R = c:\Program Files\R\R-2.4.1\bin\R.exe +;R = c:\progra~1\R-2.5.0\bin\R + +; Path to perl. This default to "C:\Perl\bin\perl.exe" on windows and +; simply 'perl' on unix. +; perl = c:\Perl\bin\perl.exe ; These two lines should not be modified, they are used to disable ; experimental features of PsN. use_keyboard=0 -;use_database=1 +use_database=0 ; Further experimental features -;database_server=doris.biof.uu.se +;database_server=localhost ;default_project=psn ;default_user=psn -;min_fork_delay=0 -;ax_fork_delay=0 - ; Set the job polling interval to a value that is suitable to your ; system. The general rule is that the larger the distributed system ; gets, the longer the polling interval needs to be. Slow systems, @@ -81,9 +82,9 @@ default=c:\nmvi,6 ; this: ; name=c:\fortran\fl32 -;[compiler] +[compiler] ; Gnu fortran compiler -;name=g77 +name=g77 ;options=-W -static -O ;[compiler] @@ -96,16 +97,11 @@ default=c:\nmvi,6 ;name=fl32 ;options=/Ox /Op -[compiler] +;[compiler] ;;Digitial Visual Fortran 5.0 -name=df +;name=df ;options=/optimize:4 /fltconsistency /fpe:3 -options=/optimize:1 /fpe:0 - -[compiler] -; Intel Fortran -name=ifort -options=-O3 +;options=/optimize:1 /fpe:0 [default_options] ; Options valid for all tools diff --git a/lib/tool/.cvsignore b/lib/tool/.cvsignore index 734c4f2..efd76fc 100644 --- a/lib/tool/.cvsignore +++ b/lib/tool/.cvsignore @@ -5,3 +5,4 @@ modelfit.pm scm.pm xv_step.pm xv.pm +mc.pm diff --git a/lib/tool/bootstrap_subs.pm b/lib/tool/bootstrap_subs.pm index 4b09a6a..61f925f 100644 --- a/lib/tool/bootstrap_subs.pm +++ b/lib/tool/bootstrap_subs.pm @@ -895,6 +895,13 @@ start modelfit_analyze unshift( @{$param_names[$i]}, 'OFV' ); push( @{$diagnostic_names[$i]}, @tmp_names ); } + if( defined $PsN::config -> {'_'} -> {'R'} and + -e $PsN::lib_dir . '/R-scripts/bootstrap.R' ) { + # copy the bootstrap R-script + cp ( $PsN::lib_dir . '/R-scripts/bootstrap.R', $self -> {'directory'} ); + # Execute the script + system( $PsN::config -> {'_'} -> {'R'}." CMD BATCH bootstrap.R" ); + } } end modelfit_analyze diff --git a/lib/tool/cdd_subs.pm b/lib/tool/cdd_subs.pm index c05f9a8..39ce861 100644 --- a/lib/tool/cdd_subs.pm +++ b/lib/tool/cdd_subs.pm @@ -45,7 +45,7 @@ start new if ( $PsN::config -> {'_'} -> {'use_database'} ) { my( $found_log, $found_cdd_id ) = $this -> read_cdd_log; - $this -> register_in_database unless ( $found_cdd_id ); + $this -> register_cdd_in_database unless ( $found_cdd_id ); $this -> log_object unless ( $found_log and $found_cdd_id ); print "Found ",$this -> {'cdd_id'},"\n"; @@ -55,43 +55,35 @@ end new # }}} new -# {{{ register_in_database +# {{{ register_cdd_in_database -start register_in_database +start register_cdd_in_database { if ( $PsN::config -> {'_'} -> {'use_database'} ) { my $dbh = DBI -> connect("DBI:mysql:host=".$PsN::config -> {'_'} -> {'database_server'}. ";databse=".$PsN::config -> {'_'} -> {'project'}, $PsN::config -> {'_'} -> {'user'}, - $PsN::config -> {'_'} -> {'password'}, + $PsN::config -> {'_'} -> {'password'}, {'RaiseError' => 1}); my $sth; - # bins and case_column can be defined for more than one - # model. We nevertheless begin by implementing this. - print "CC: ".$self -> {'case_columns'}."\n"; - print("INSERT INTO ".$PsN::config -> {'_'} -> {'project'}. - ".cdd ( bins, case_column,xv ) ". - "VALUES ( '".$self -> {'bins'}. - "', '".$self -> {'case_columns'}. - "', '".$self -> {'cross_validate'}."' )\n"); + # bins and case_column can be defined for more than one model. Skip + # registration of these for now. +# $sth = $dbh -> prepare("INSERT INTO ".$PsN::config -> {'_'} -> {'project'}. +# ".cdd ( tool_id, bins, case_column ) ". +# "VALUES (".$self -> {'tool_id'}.", '".$self -> {'bins'}. +# "', '".$self -> {'case_column'}."' )"); $sth = $dbh -> prepare("INSERT INTO ".$PsN::config -> {'_'} -> {'project'}. - ".cdd ( bins, case_column,xv ) ". - "VALUES ( '".$self -> {'bins'}. - "', '".$self -> {'case_columns'}. - "', '".$self -> {'cross_validate'}."' )"); -# $sth = $dbh -> prepare("INSERT INTO ".$PsN::config -> {'_'} -> {'project'}. -# ".cdd ( tool_id ) ". -# "VALUES (".$self -> {'tool_id'}." )"); + ".cdd ( tool_id ) ". + "VALUES (".$self -> {'tool_id'}." )"); $sth -> execute; $self -> {'cdd_id'} = $sth->{'mysql_insertid'}; $sth -> finish; $dbh -> disconnect; - tool::register_in_database( $self, cdd_id => $self -> {'cdd_id'} ); } } -end register_in_database +end register_cdd_in_database -# }}} register_in_database +# }}} register_cdd_in_database # {{{ register_mfit_results @@ -1440,6 +1432,13 @@ start modelfit_analyze # experimental: to save memory $self -> {'prepared_models'}[$model_number-1]{'own'} = undef; + if( defined $PsN::config -> {'_'} -> {'R'} and + -e $PsN::lib_dir . '/R-scripts/cdd.R' ) { + # copy the cdd R-script + cp ( $PsN::lib_dir . '/R-scripts/cdd.R', $self -> {'directory'} ); + # Execute the script + system( $PsN::config -> {'_'} -> {'R'}." CMD BATCH cdd.R" ); + } } end modelfit_analyze diff --git a/lib/tool/llp_subs.pm b/lib/tool/llp_subs.pm index 2070563..c6d36ed 100644 --- a/lib/tool/llp_subs.pm +++ b/lib/tool/llp_subs.pm @@ -811,6 +811,14 @@ start modelfit_analyze $self -> {'raw_results'}[$model_number-1] = $self -> {'tools'} -> [0] -> raw_results if( defined $self -> {'tools'} -> [0] ); } + if( $self -> iteration() < 2 and + defined $PsN::config -> {'_'} -> {'R'} and + -e $PsN::lib_dir . '/R-scripts/llp.R' ) { + # copy the llp R-script + cp ( $PsN::lib_dir . '/R-scripts/llp.R', $self -> {'directory'} ); + # Execute the script + system( $PsN::config -> {'_'} -> {'R'}." CMD BATCH llp.R" ); + } } end modelfit_analyze diff --git a/lib/tool/mc_subs.pm b/lib/tool/mc_subs.pm index 1e4ef4a..2759f95 100644 --- a/lib/tool/mc_subs.pm +++ b/lib/tool/mc_subs.pm @@ -93,6 +93,8 @@ if ( not $done ) { my @sim_models; my @table_header; my @all_simulated_files; + my ( @orig_table_names, @alt_table_names ); + # Copy the model to a new simulation models for( my $sim_no = 1; $sim_no <= $self -> {'samples'}; $sim_no++ ) { my $sim_name = "mc-$sim_no.sim"; @@ -114,12 +116,16 @@ if ( not $done ) { copy_data => 0, copy_output => 0); $est_original -> drop_dropped; + my $tbl_nm_ref = $model -> table_names(); + @orig_table_names = @{$tbl_nm_ref} if( defined $tbl_nm_ref ); $est_alternative = $alternative -> copy( filename => $self -> {'directory'}.'m'.$model_number.'/'.$alt_name, target => 'mem', copy_data => 0, copy_output => 0); $est_alternative -> drop_dropped; + my $tbl_nm_ref = $alternative -> table_names(); + @alt_table_names = @{$tbl_nm_ref} if( defined $tbl_nm_ref ); } else { $sim_model = $sim_models[0] -> copy( filename => $self -> {'directory'}.'m'.$model_number.'/'.$sim_name, @@ -143,9 +149,27 @@ if ( not $done ) { $est_original -> ignore_missing_files( 1 ); $est_original -> outputfile( $self -> {'directory'}.'m'.$model_number.'/'.$orig_out ); $est_original -> ignore_missing_files( 0 ); + my @new_orig_table_names; + for( my $pr = 0; $pr <= $#orig_table_names; $pr++ ) { + for( my $tbl = 0; $tbl < scalar @{$orig_table_names[$pr]}; $tbl++ ) { + $new_orig_table_names[$pr][$tbl] = $orig_table_names[$pr][$tbl].'-'.$sim_no; + } + } + if( $#new_orig_table_names >= 0 ) { + $est_original -> table_names( new_names => \@new_orig_table_names ); + } $est_alternative -> ignore_missing_files( 1 ); $est_alternative -> outputfile( $self -> {'directory'}.'m'.$model_number.'/'.$alt_out ); $est_alternative -> ignore_missing_files( 0 ); + my @new_alt_table_names; + for( my $pr = 0; $pr <= $#alt_table_names; $pr++ ) { + for( my $tbl = 0; $tbl < scalar @{$alt_table_names[$pr]}; $tbl++ ) { + $new_alt_table_names[$pr][$tbl] = $alt_table_names[$pr][$tbl].'-'.$sim_no; + } + } + if( $#new_alt_table_names >= 0 ) { + $est_alternative -> table_names( new_names => \@new_alt_table_names ); + } if( $self -> shrinkage() ) { $est_original -> shrinkage_stats( enabled => 1 ); $est_alternative -> shrinkage_stats( enabled => 1 ); @@ -257,15 +281,19 @@ if ( not $done ) { filename => $orig_name, outputfile => $orig_out, extra_files => $model -> extra_files, - target => 'disk', - ignore_missing_files => 1 ); + target => 'mem', + ignore_missing_files => 1, + extra_output => $model -> extra_output(), + cwres => $model -> cwres() ); my $est_alternative = model -> new( directory => $model_dir, filename => $alt_name, outputfile => $alt_out, extra_files => $alternative -> extra_files, - target => 'disk', - ignore_missing_files => 1 ); + target => 'mem', + ignore_missing_files => 1, + extra_output => $model -> extra_output(), + cwres => $model -> cwres() ); push( @orig_est_models, $est_original ); push( @alt_est_models, $est_alternative ); my $nl = $j == $stored_samples ? "" : "\r"; diff --git a/lib/tool/modelfit_subs.pm b/lib/tool/modelfit_subs.pm index b24b801..50e7286 100644 --- a/lib/tool/modelfit_subs.pm +++ b/lib/tool/modelfit_subs.pm @@ -396,8 +396,14 @@ start prepare_raw_results # Find the model with most parameter of each kind and put the # number of the parameter in "max_hash". + # %max_hash should be initiated and filled in the constructor. + my ( %max_hash ); #, %category_names ); for ( my $i = 0; $i < scalar @{$self -> {'models'}}; $i++ ) { # models level + unless( $self -> {'models'} -> [$i] -> outputs -> [0] -> parsed ){ + $self -> {'models'} -> [$i] -> outputs -> [0] -> abort_on_fail(0); + $self -> {'models'} -> [$i] -> outputs -> [0] -> _read_problems; + } # Some column in "raw_results_header" are meta-columns, they # will be replaced by several columns. For example, the @@ -407,7 +413,7 @@ start prepare_raw_results # column of the raw_results_header to find the maximum # number of real columns. - foreach my $category ( @{$self -> {'raw_results_header'}},'npomega' ) { + foreach my $category ( @{$self -> {'raw_results_header'}},'npomega' ) { if ( $category eq 'setheta' or $category eq 'seomega' or $category eq 'sesigma' ){ next; } elsif ( $category eq 'theta' or $category eq 'omega' or $category eq 'sigma' or @@ -441,7 +447,6 @@ start prepare_raw_results my $labels; if( $self -> {'models'} -> [$i] -> outputs -> [0] -> parsed and $self -> {'models'} -> [$i] -> outputs -> [0] -> parsed_successfully ){ - $labels = $self -> {'models'} -> [$i] -> {'outputs'} -> [0] -> labels( parameter_type => $category ); } # we can't use labels directly since different models may have different @@ -470,13 +475,14 @@ start prepare_raw_results # {{{ values + # This method should be called with a model number and should + # update $self -> {'results_file'}. Through this it should be + # possible to print the raw_results_file (and other files as + # well) during the execution of the method. + my $pushed_rows = 0; # All rows pushed on result array in previous models my $raw_line_structure = ext::Config::Tiny -> new( ); for ( my $i = 0; $i < scalar @{$self -> {'models'}}; $i++ ) { # models level - unless( $self -> {'models'} -> [$i] -> outputs -> [0] -> parsed ){ - $self -> {'models'} -> [$i] -> outputs -> [0] -> abort_on_fail(0); - $self -> {'models'} -> [$i] -> outputs -> [0] -> _read_problems; - } if( $self -> {'models'} -> [$i] -> outputs -> [0] -> parsed_successfully ){ my @probs = @{$self -> {'models'} -> [$i] -> {'outputs'} -> [0] -> problem_structure}; my $np = scalar @probs; # #probs @@ -513,7 +519,8 @@ start prepare_raw_results defined $prob -> [0] and ref $prob -> [0] eq 'ARRAY' and defined $self -> {'raw_results'} and defined $self -> {'raw_results'} -> [$i+$prob_num] ){ - $raw_line_structure -> { $i+$prob_num }{ $category } = scalar @{$self -> {'raw_results'} -> [$i+$prob_num]} . ",". scalar @{$prob -> [0]}; + my $num = scalar @{$self -> {'raw_results'} -> [$i+$prob_num]} . ",". scalar @{$prob -> [0]}; + $raw_line_structure -> { $i+$prob_num }{ $category } = $num; } $prob_num++; } @@ -602,7 +609,7 @@ start prepare_raw_results my $row = $pushed_rows+1; push( @{$self -> {'raw_results'} -> [$pushed_rows++]}, ($i+1). ",run failed - Could not parse the output file: ". - $self -> {'models'} -> [$i] -> {'outputs'} -> [0] -> filename ); + $self -> {'models'} -> [$i] -> {'outputs'} -> [0] -> filename ); } } $raw_line_structure -> write( 'raw_file_structure' ); @@ -745,7 +752,7 @@ start copy_model_and_input } else { debug -> die( message => 'No datafiles set in modelfile.' ); } - + # copy the msfi files if( defined $model -> msfi_names() ){ foreach my $msfi_files( @{$model -> msfi_names()} ){ @@ -757,6 +764,16 @@ start copy_model_and_input } } + # copy the msfo files if msfo_resume + if( $self -> {'msfo_resume'} ){ + foreach my $msfo_files( @{$model -> msfo_names()} ){ + foreach my $msfo_file( @{$msfo_files} ){ + my ( $dir, $filename ) = OSspecific::absolute_path($model -> directory, + $msfo_file ); + cp( $dir.$filename, $filename ); + } + } + } # Copy extra data files to temporary dirctory and set short version names my @new_extra_data_names; my @problems = @{$model -> problems}; @@ -843,8 +860,18 @@ start copy_model_and_output { my $outfilename = $model -> outputs -> [0] -> full_name; + my ($dir, $model_filename) = OSspecific::absolute_path($model -> directory, + $model -> filename ); + + # This is used with 'prepend_model_file_name' + my $dotless_model_filename = $model_filename; + $dotless_model_filename =~ s/\.[^.]+$//; + + # Copy $use_run files to files without numbers, to avoid confusion. + cp( "psn-$use_run.lst", 'psn.lst' ) if ( $use_run ne '' ); cp( "psn.lst", $outfilename ); + if( defined $model -> table_names ){ foreach my $table_files( @{$model -> table_names} ){ foreach my $table_file( @{$table_files} ){ @@ -852,29 +879,62 @@ start copy_model_and_output } } } + my $final_output = output -> new( filename => $outfilename, model_id => $model -> model_id ); $final_output -> register_in_database( model_id => $model -> model_id, force => 1 ); # If we are here, the model has been run $final_model -> outputs( [$final_output] ); + if( defined $model -> msfo_names() ){ foreach my $msfo_files( @{$model -> msfo_names()} ){ foreach my $msfo_file( @{$msfo_files} ){ my ( $dir, $filename ) = OSspecific::absolute_path($model -> directory, $msfo_file ); - cp( $filename, $dir.$filename ); + if( $self -> {'prepend_model_file_name'} ) { + cp( $filename, $dir.$dotless_model_filename.'.'.$filename ); + } else { + cp( $filename, $dir.$filename ); + } } } - $final_model -> msfo_names( new_names => $model -> msfo_names() ); + #$final_model -> msfo_names( new_names => $model -> msfo_names() ); } - + if( defined $model -> table_names ){ foreach my $table_files( @{$model -> table_names} ){ foreach my $table_file( @{$table_files} ){ my ( $dir, $filename ) = OSspecific::absolute_path($model -> directory, $table_file ); - cp( $filename, $dir.$filename ); + if( $self -> unwrap_table_files() ) { + open( TABLE, '<'.$filename ); + my @table =