aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Lozano <llozano@chromium.org>2013-03-15 14:44:13 -0700
committerChromeBot <chrome-bot@google.com>2013-03-15 15:51:37 -0700
commitf81680c018729fd4499e1e200d04b48c4b90127c (patch)
tree940608da8374604b82edfdb2d7df55d065f05d4c
parent2296ee0b914aba5bba07becab4ff68884ce9b8a5 (diff)
downloadtoolchain-utils-f81680c018729fd4499e1e200d04b48c4b90127c.tar.gz
Cleaned up directory after copy of tools from perforce directory
Got rid of stale copies of some tools like "crosperf" and moved all files under v14 directory (that came from perforce) into the top directory. BUG=None TEST=None Change-Id: I408d17a36ceb00e74db71403d2351fd466a14f8e Reviewed-on: https://gerrit-int.chromium.org/33887 Tested-by: Luis Lozano <llozano@chromium.org> Reviewed-by: Yunlian Jiang <yunlian@google.com> Commit-Queue: Luis Lozano <llozano@chromium.org>
-rw-r--r--.gitignore (renamed from v14/.gitignore)0
-rw-r--r--automation/PRESUBMIT.py (renamed from v14/automation/PRESUBMIT.py)0
-rw-r--r--automation/__init__.py (renamed from v14/automation/__init__.py)0
-rw-r--r--automation/all_tests.py (renamed from v14/automation/all_tests.py)0
-rw-r--r--automation/clients/__init__.py (renamed from v14/automation/clients/__init__.py)0
-rwxr-xr-xautomation/clients/android.py (renamed from v14/automation/clients/android.py)0
-rwxr-xr-xautomation/clients/chromeos.py (renamed from v14/automation/clients/chromeos.py)0
-rwxr-xr-xautomation/clients/crosstool.py (renamed from v14/automation/clients/crosstool.py)0
-rwxr-xr-xautomation/clients/dejagnu_compiler.py (renamed from v14/automation/clients/dejagnu_compiler.py)0
-rw-r--r--automation/clients/helper/__init__.py (renamed from v14/automation/clients/helper/__init__.py)0
-rw-r--r--automation/clients/helper/android.py (renamed from v14/automation/clients/helper/android.py)0
-rw-r--r--automation/clients/helper/chromeos.py (renamed from v14/automation/clients/helper/chromeos.py)0
-rw-r--r--automation/clients/helper/crosstool.py (renamed from v14/automation/clients/helper/crosstool.py)0
-rw-r--r--automation/clients/helper/jobs.py (renamed from v14/automation/clients/helper/jobs.py)0
-rw-r--r--automation/clients/helper/perforce.py (renamed from v14/automation/clients/helper/perforce.py)0
-rwxr-xr-xautomation/clients/nightly.py (renamed from v14/automation/clients/nightly.py)0
-rwxr-xr-xautomation/clients/output_test.py (renamed from v14/automation/clients/output_test.py)0
-rwxr-xr-xautomation/clients/pwd_test.py (renamed from v14/automation/clients/pwd_test.py)0
-rwxr-xr-xautomation/clients/report/dejagnu.sh (renamed from v14/automation/clients/report/dejagnu.sh)0
-rw-r--r--automation/clients/report/dejagnu/__init__.py (renamed from v14/automation/clients/report/dejagnu/__init__.py)0
-rw-r--r--automation/clients/report/dejagnu/main.py (renamed from v14/automation/clients/report/dejagnu/main.py)0
-rw-r--r--automation/clients/report/dejagnu/manifest.py (renamed from v14/automation/clients/report/dejagnu/manifest.py)0
-rw-r--r--automation/clients/report/dejagnu/report.html (renamed from v14/automation/clients/report/dejagnu/report.html)0
-rw-r--r--automation/clients/report/dejagnu/report.py (renamed from v14/automation/clients/report/dejagnu/report.py)0
-rw-r--r--automation/clients/report/dejagnu/summary.py (renamed from v14/automation/clients/report/dejagnu/summary.py)0
-rwxr-xr-xautomation/clients/report/validate_failures.py (renamed from v14/automation/clients/report/validate_failures.py)0
-rw-r--r--automation/common/__init__.py (renamed from v14/automation/common/__init__.py)0
-rw-r--r--automation/common/command.py (renamed from v14/automation/common/command.py)0
-rw-r--r--automation/common/command_executer.py (renamed from v14/automation/common/command_executer.py)0
-rwxr-xr-xautomation/common/command_executer_test.py (renamed from v14/automation/common/command_executer_test.py)0
-rw-r--r--automation/common/events.py (renamed from v14/automation/common/events.py)0
-rw-r--r--automation/common/job.py (renamed from v14/automation/common/job.py)0
-rw-r--r--automation/common/job_group.py (renamed from v14/automation/common/job_group.py)0
-rw-r--r--automation/common/logger.py (renamed from v14/automation/common/logger.py)0
-rw-r--r--automation/common/machine.py (renamed from v14/automation/common/machine.py)0
-rwxr-xr-xautomation/common/machine_test.py (renamed from v14/automation/common/machine_test.py)0
-rw-r--r--automation/common/state_machine.py (renamed from v14/automation/common/state_machine.py)0
-rw-r--r--automation/server/__init__.py (renamed from v14/automation/server/__init__.py)0
-rw-r--r--automation/server/job_executer.py (renamed from v14/automation/server/job_executer.py)0
-rw-r--r--automation/server/job_group_manager.py (renamed from v14/automation/server/job_group_manager.py)0
-rw-r--r--automation/server/job_manager.py (renamed from v14/automation/server/job_manager.py)0
-rw-r--r--automation/server/machine_manager.py (renamed from v14/automation/server/machine_manager.py)0
-rwxr-xr-xautomation/server/machine_manager_test.py (renamed from v14/automation/server/machine_manager_test.py)0
-rw-r--r--automation/server/monitor/__init__.py (renamed from v14/automation/server/monitor/__init__.py)0
-rw-r--r--automation/server/monitor/dashboard.py (renamed from v14/automation/server/monitor/dashboard.py)0
-rwxr-xr-xautomation/server/monitor/manage.py (renamed from v14/automation/server/monitor/manage.py)0
-rw-r--r--automation/server/monitor/settings.py (renamed from v14/automation/server/monitor/settings.py)0
-rwxr-xr-xautomation/server/monitor/start.sh (renamed from v14/automation/server/monitor/start.sh)0
-rw-r--r--automation/server/monitor/static/style.css (renamed from v14/automation/server/monitor/static/style.css)0
-rw-r--r--automation/server/monitor/templates/base.html (renamed from v14/automation/server/monitor/templates/base.html)0
-rw-r--r--automation/server/monitor/templates/job.html (renamed from v14/automation/server/monitor/templates/job.html)0
-rw-r--r--automation/server/monitor/templates/job_group.html (renamed from v14/automation/server/monitor/templates/job_group.html)0
-rw-r--r--automation/server/monitor/templates/job_group_list.html (renamed from v14/automation/server/monitor/templates/job_group_list.html)0
-rw-r--r--automation/server/monitor/templates/job_log.html (renamed from v14/automation/server/monitor/templates/job_log.html)0
-rw-r--r--automation/server/monitor/templates/machine_list.html (renamed from v14/automation/server/monitor/templates/machine_list.html)0
-rw-r--r--automation/server/monitor/templates/snippet_attribute_table.html (renamed from v14/automation/server/monitor/templates/snippet_attribute_table.html)0
-rw-r--r--automation/server/monitor/templates/snippet_code.html (renamed from v14/automation/server/monitor/templates/snippet_code.html)0
-rw-r--r--automation/server/monitor/templates/snippet_links.html (renamed from v14/automation/server/monitor/templates/snippet_links.html)0
-rw-r--r--automation/server/monitor/urls.py (renamed from v14/automation/server/monitor/urls.py)0
-rwxr-xr-xautomation/server/server.py (renamed from v14/automation/server/server.py)0
-rwxr-xr-xautomation/server/server_test.py (renamed from v14/automation/server/server_test.py)0
-rw-r--r--automation/server/test_pool.csv (renamed from v14/automation/server/test_pool.csv)0
-rw-r--r--build-binutils/opts.sh (renamed from v14/build-binutils/opts.sh)0
-rw-r--r--build-gcc/opts.sh (renamed from v14/build-gcc/opts.sh)0
-rwxr-xr-xbuild_benchmarks.py (renamed from v14/build_benchmarks.py)0
-rwxr-xr-xbuild_chrome_browser.py (renamed from v14/build_chrome_browser.py)0
-rwxr-xr-xbuild_chromeos.py (renamed from v14/build_chromeos.py)0
-rwxr-xr-xbuild_tc.py (renamed from v14/build_tc.py)0
-rwxr-xr-xcommand_executer_timeout_test.py (renamed from v14/command_executer_timeout_test.py)0
-rwxr-xr-xcompare_benchmarks.py (renamed from v14/compare_benchmarks.py)0
-rw-r--r--crb/autotest_gatherer.py (renamed from v14/crb/autotest_gatherer.py)0
-rw-r--r--crb/autotest_run.py (renamed from v14/crb/autotest_run.py)0
-rwxr-xr-xcrb/crb_driver.py (renamed from v14/crb/crb_driver.py)0
-rw-r--r--crb/machine_manager_singleton.py (renamed from v14/crb/machine_manager_singleton.py)0
-rw-r--r--crb/table_formatter.py (renamed from v14/crb/table_formatter.py)0
-rwxr-xr-xcros_login.py (renamed from v14/cros_login.py)0
-rw-r--r--crosperf/benchmark.py4
-rw-r--r--crosperf/benchmark_run.py7
-rwxr-xr-xcrosperf/benchmark_run_unittest.py12
-rw-r--r--crosperf/config.py (renamed from v14/crosperf/config.py)0
-rwxr-xr-xcrosperf/crosperf.py13
-rw-r--r--crosperf/experiment.py23
-rw-r--r--crosperf/experiment_factory.py27
-rwxr-xr-xcrosperf/experiment_factory_unittest.py4
-rw-r--r--crosperf/experiment_runner.py8
-rw-r--r--crosperf/image_checksummer.py38
-rw-r--r--crosperf/label.py8
-rw-r--r--crosperf/machine_manager.py47
-rwxr-xr-xcrosperf/machine_manager_unittest.py8
-rw-r--r--crosperf/perf_table.py39
-rw-r--r--crosperf/results_cache.py84
-rw-r--r--crosperf/results_organizer.py13
-rw-r--r--crosperf/results_report.py15
-rw-r--r--crosperf/settings_factory.py29
-rw-r--r--cwp/bartlett/app.yaml (renamed from v14/cwp/bartlett/app.yaml)0
-rwxr-xr-xcwp/bartlett/server.py (renamed from v14/cwp/bartlett/server.py)0
-rw-r--r--cwp/bartlett/static/favicon.ico (renamed from v14/cwp/bartlett/static/favicon.ico)bin198 -> 198 bytes
-rw-r--r--cwp/bartlett/test/server_tester.py (renamed from v14/cwp/bartlett/test/server_tester.py)0
-rwxr-xr-xcwp/bartlett/update_appengine_server (renamed from v14/cwp/bartlett/update_appengine_server)0
-rw-r--r--cwp/demo_pipeline.sh (renamed from v14/cwp/demo_pipeline.sh)0
-rw-r--r--cwp/interpreter/app_engine_pull.py (renamed from v14/cwp/interpreter/app_engine_pull.py)0
-rw-r--r--cwp/interpreter/symbolizer.py (renamed from v14/cwp/interpreter/symbolizer.py)0
-rw-r--r--cwp/performance/experiment_gen.py (renamed from v14/cwp/performance/experiment_gen.py)0
-rw-r--r--dejagnu/__init__.py (renamed from v14/dejagnu/__init__.py)0
-rw-r--r--dejagnu/boards/chromeos-machine.exp (renamed from v14/dejagnu/boards/chromeos-machine.exp)0
-rw-r--r--dejagnu/chromeos.exp.in (renamed from v14/dejagnu/chromeos.exp.in)0
-rwxr-xr-xdejagnu/run_dejagnu.py (renamed from v14/dejagnu/run_dejagnu.py)0
-rw-r--r--dejagnu/site.exp (renamed from v14/dejagnu/site.exp)0
-rwxr-xr-xfdo_scripts/divide_and_merge_profiles.py (renamed from v14/fdo_scripts/divide_and_merge_profiles.py)0
-rwxr-xr-xfdo_scripts/divide_and_merge_profiles_test.py (renamed from v14/fdo_scripts/divide_and_merge_profiles_test.py)0
-rwxr-xr-xfdo_scripts/profile_cycler.py (renamed from v14/fdo_scripts/profile_cycler.py)0
-rw-r--r--fdo_scripts/summarize_hot_blocks.py (renamed from v14/fdo_scripts/summarize_hot_blocks.py)0
-rw-r--r--fdo_scripts/vanilla_vs_fdo.py (renamed from v14/fdo_scripts/vanilla_vs_fdo.py)0
-rwxr-xr-xget_common_image_version.py (renamed from v14/get_common_image_version.py)0
-rwxr-xr-ximage_chromeos.py18
-rwxr-xr-xlock_machine.py (renamed from v14/lock_machine.py)0
-rw-r--r--lock_machine_test.py (renamed from v14/lock_machine_test.py)0
-rwxr-xr-xproduce_output.py (renamed from v14/produce_output.py)0
-rwxr-xr-xpyrun (renamed from v14/pyrun)0
-rwxr-xr-xremote_gcc_build.py (renamed from v14/remote_gcc_build.py)0
-rwxr-xr-xremote_kill_test.py (renamed from v14/remote_kill_test.py)0
-rwxr-xr-xremote_test.py (renamed from v14/remote_test.py)0
-rwxr-xr-xrepo_to_repo.py (renamed from v14/repo_to_repo.py)0
-rw-r--r--repo_to_repo_files/binutils-master.rtr (renamed from v14/repo_to_repo_files/binutils-master.rtr)0
-rw-r--r--repo_to_repo_files/binutils-mobile_toolchain_v16.rtr (renamed from v14/repo_to_repo_files/binutils-mobile_toolchain_v16.rtr)0
-rw-r--r--repo_to_repo_files/crosperf.rtr (renamed from v14/repo_to_repo_files/crosperf.rtr)0
-rw-r--r--repo_to_repo_files/gcc-branches_google_4_7.rtr (renamed from v14/repo_to_repo_files/gcc-branches_google_4_7.rtr)0
-rw-r--r--repo_to_repo_files/gcc-branches_google_main.rtr (renamed from v14/repo_to_repo_files/gcc-branches_google_main.rtr)0
-rw-r--r--repo_to_repo_files/gcc-master.rtr (renamed from v14/repo_to_repo_files/gcc-master.rtr)0
-rw-r--r--repo_to_repo_files/gdb-master.rtr (renamed from v14/repo_to_repo_files/gdb-master.rtr)0
-rw-r--r--repo_to_repo_files/toolchain-utils.rtr (renamed from v14/repo_to_repo_files/toolchain-utils.rtr)0
-rwxr-xr-xreport_generator.py (renamed from v14/report_generator.py)0
-rwxr-xr-xrun_benchmarks.py (renamed from v14/run_benchmarks.py)0
-rwxr-xr-xrun_tests.py (renamed from v14/run_tests.py)0
-rwxr-xr-xsetup_chromeos.py (renamed from v14/setup_chromeos.py)0
-rwxr-xr-xsheriff_rotation.py (renamed from v14/sheriff_rotation.py)0
-rwxr-xr-xsummarize_results.py (renamed from v14/summarize_results.py)0
-rwxr-xr-xtc_enter_chroot.py (renamed from v14/tc_enter_chroot.py)0
-rwxr-xr-xtest_gcc_dejagnu.py (renamed from v14/test_gcc_dejagnu.py)0
-rw-r--r--test_toolchains.py (renamed from v14/test_toolchains.py)0
-rwxr-xr-xutils/buildbot_json.py (renamed from v14/utils/buildbot_json.py)0
-rw-r--r--utils/command_executer.py15
-rwxr-xr-xutils/command_executer_unittest.py (renamed from v14/utils/command_executer_unittest.py)0
-rw-r--r--utils/logger.py10
-rw-r--r--utils/misc.py25
-rwxr-xr-xutils/perf_diff.py12
-rw-r--r--utils/tabulator.py169
-rw-r--r--utils/tabulator_test.py4
-rw-r--r--v14/README10
-rw-r--r--v14/crosperf/autotest_runner.py40
-rw-r--r--v14/crosperf/benchmark.py26
-rw-r--r--v14/crosperf/benchmark_run.py198
-rwxr-xr-xv14/crosperf/benchmark_run_unittest.py50
-rw-r--r--v14/crosperf/column_chart.py57
-rwxr-xr-xv14/crosperf/crosperf2
-rwxr-xr-xv14/crosperf/crosperf.py108
-rwxr-xr-xv14/crosperf/crosperf_test.py40
-rw-r--r--v14/crosperf/default_remotes5
-rw-r--r--v14/crosperf/experiment.py127
-rw-r--r--v14/crosperf/experiment_factory.py135
-rwxr-xr-xv14/crosperf/experiment_factory_unittest.py55
-rw-r--r--v14/crosperf/experiment_file.py185
-rwxr-xr-xv14/crosperf/experiment_file_unittest.py110
-rw-r--r--v14/crosperf/experiment_files/README26
-rw-r--r--v14/crosperf/experiment_files/aes_perf7
-rw-r--r--v14/crosperf/experiment_files/bloat_perf6
-rw-r--r--v14/crosperf/experiment_files/morejs_perf6
-rw-r--r--v14/crosperf/experiment_files/page_cycler6
-rw-r--r--v14/crosperf/experiment_files/page_cycler_perf43
-rw-r--r--v14/crosperf/experiment_files/toolchain16
-rw-r--r--v14/crosperf/experiment_runner.py132
-rw-r--r--v14/crosperf/experiment_status.py88
-rw-r--r--v14/crosperf/field.py108
-rw-r--r--v14/crosperf/help.py106
-rw-r--r--v14/crosperf/image_checksummer.py63
-rw-r--r--v14/crosperf/label.py54
-rw-r--r--v14/crosperf/machine_manager.py419
-rwxr-xr-xv14/crosperf/machine_manager_unittest.py67
-rw-r--r--v14/crosperf/perf_table.py85
-rw-r--r--v14/crosperf/results_cache.py417
-rw-r--r--v14/crosperf/results_organizer.py108
-rw-r--r--v14/crosperf/results_report.py502
-rw-r--r--v14/crosperf/results_sorter.py49
-rwxr-xr-xv14/crosperf/run_tests.sh13
-rw-r--r--v14/crosperf/settings.py62
-rw-r--r--v14/crosperf/settings_factory.py144
-rw-r--r--v14/crosperf/test_flag.py16
-rwxr-xr-xv14/image_chromeos.py320
-rw-r--r--v14/utils/__init__.py0
-rw-r--r--v14/utils/colortrans.py376
-rw-r--r--v14/utils/command_executer.py338
-rw-r--r--v14/utils/constants.py10
-rw-r--r--v14/utils/email_sender.py62
-rw-r--r--v14/utils/file_utils.py89
-rw-r--r--v14/utils/html_tools.py93
-rw-r--r--v14/utils/logger.py195
-rw-r--r--v14/utils/misc.py327
-rw-r--r--v14/utils/misc_test.py50
-rwxr-xr-xv14/utils/perf_diff.py324
-rw-r--r--v14/utils/pstat.py1068
-rw-r--r--v14/utils/stats.py4528
-rw-r--r--v14/utils/tabulator.py1125
-rw-r--r--v14/utils/tabulator_test.py135
-rw-r--r--v14/utils/timeline.py51
-rw-r--r--v14/utils/timeline_test.py54
205 files changed, 465 insertions, 13003 deletions
diff --git a/v14/.gitignore b/.gitignore
index d0b39e30..d0b39e30 100644
--- a/v14/.gitignore
+++ b/.gitignore
diff --git a/v14/automation/PRESUBMIT.py b/automation/PRESUBMIT.py
index 56a43e6c..56a43e6c 100644
--- a/v14/automation/PRESUBMIT.py
+++ b/automation/PRESUBMIT.py
diff --git a/v14/automation/__init__.py b/automation/__init__.py
index e69de29b..e69de29b 100644
--- a/v14/automation/__init__.py
+++ b/automation/__init__.py
diff --git a/v14/automation/all_tests.py b/automation/all_tests.py
index 3ca4f52a..3ca4f52a 100644
--- a/v14/automation/all_tests.py
+++ b/automation/all_tests.py
diff --git a/v14/automation/clients/__init__.py b/automation/clients/__init__.py
index e69de29b..e69de29b 100644
--- a/v14/automation/clients/__init__.py
+++ b/automation/clients/__init__.py
diff --git a/v14/automation/clients/android.py b/automation/clients/android.py
index 069fcafb..069fcafb 100755
--- a/v14/automation/clients/android.py
+++ b/automation/clients/android.py
diff --git a/v14/automation/clients/chromeos.py b/automation/clients/chromeos.py
index ec80a0eb..ec80a0eb 100755
--- a/v14/automation/clients/chromeos.py
+++ b/automation/clients/chromeos.py
diff --git a/v14/automation/clients/crosstool.py b/automation/clients/crosstool.py
index 9844174b..9844174b 100755
--- a/v14/automation/clients/crosstool.py
+++ b/automation/clients/crosstool.py
diff --git a/v14/automation/clients/dejagnu_compiler.py b/automation/clients/dejagnu_compiler.py
index 4bc881e0..4bc881e0 100755
--- a/v14/automation/clients/dejagnu_compiler.py
+++ b/automation/clients/dejagnu_compiler.py
diff --git a/v14/automation/clients/helper/__init__.py b/automation/clients/helper/__init__.py
index 8b137891..8b137891 100644
--- a/v14/automation/clients/helper/__init__.py
+++ b/automation/clients/helper/__init__.py
diff --git a/v14/automation/clients/helper/android.py b/automation/clients/helper/android.py
index f49ccb86..f49ccb86 100644
--- a/v14/automation/clients/helper/android.py
+++ b/automation/clients/helper/android.py
diff --git a/v14/automation/clients/helper/chromeos.py b/automation/clients/helper/chromeos.py
index 4005390e..4005390e 100644
--- a/v14/automation/clients/helper/chromeos.py
+++ b/automation/clients/helper/chromeos.py
diff --git a/v14/automation/clients/helper/crosstool.py b/automation/clients/helper/crosstool.py
index b78e2d86..b78e2d86 100644
--- a/v14/automation/clients/helper/crosstool.py
+++ b/automation/clients/helper/crosstool.py
diff --git a/v14/automation/clients/helper/jobs.py b/automation/clients/helper/jobs.py
index e1827015..e1827015 100644
--- a/v14/automation/clients/helper/jobs.py
+++ b/automation/clients/helper/jobs.py
diff --git a/v14/automation/clients/helper/perforce.py b/automation/clients/helper/perforce.py
index 5e9c261c..5e9c261c 100644
--- a/v14/automation/clients/helper/perforce.py
+++ b/automation/clients/helper/perforce.py
diff --git a/v14/automation/clients/nightly.py b/automation/clients/nightly.py
index bf1ef5a7..bf1ef5a7 100755
--- a/v14/automation/clients/nightly.py
+++ b/automation/clients/nightly.py
diff --git a/v14/automation/clients/output_test.py b/automation/clients/output_test.py
index 7cff8eda..7cff8eda 100755
--- a/v14/automation/clients/output_test.py
+++ b/automation/clients/output_test.py
diff --git a/v14/automation/clients/pwd_test.py b/automation/clients/pwd_test.py
index 2c2118bb..2c2118bb 100755
--- a/v14/automation/clients/pwd_test.py
+++ b/automation/clients/pwd_test.py
diff --git a/v14/automation/clients/report/dejagnu.sh b/automation/clients/report/dejagnu.sh
index fadd8a0c..fadd8a0c 100755
--- a/v14/automation/clients/report/dejagnu.sh
+++ b/automation/clients/report/dejagnu.sh
diff --git a/v14/automation/clients/report/dejagnu/__init__.py b/automation/clients/report/dejagnu/__init__.py
index e69de29b..e69de29b 100644
--- a/v14/automation/clients/report/dejagnu/__init__.py
+++ b/automation/clients/report/dejagnu/__init__.py
diff --git a/v14/automation/clients/report/dejagnu/main.py b/automation/clients/report/dejagnu/main.py
index c05e3e48..c05e3e48 100644
--- a/v14/automation/clients/report/dejagnu/main.py
+++ b/automation/clients/report/dejagnu/main.py
diff --git a/v14/automation/clients/report/dejagnu/manifest.py b/automation/clients/report/dejagnu/manifest.py
index 75d907cd..75d907cd 100644
--- a/v14/automation/clients/report/dejagnu/manifest.py
+++ b/automation/clients/report/dejagnu/manifest.py
diff --git a/v14/automation/clients/report/dejagnu/report.html b/automation/clients/report/dejagnu/report.html
index 39b39e09..39b39e09 100644
--- a/v14/automation/clients/report/dejagnu/report.html
+++ b/automation/clients/report/dejagnu/report.html
diff --git a/v14/automation/clients/report/dejagnu/report.py b/automation/clients/report/dejagnu/report.py
index 7f2375de..7f2375de 100644
--- a/v14/automation/clients/report/dejagnu/report.py
+++ b/automation/clients/report/dejagnu/report.py
diff --git a/v14/automation/clients/report/dejagnu/summary.py b/automation/clients/report/dejagnu/summary.py
index c45fed44..c45fed44 100644
--- a/v14/automation/clients/report/dejagnu/summary.py
+++ b/automation/clients/report/dejagnu/summary.py
diff --git a/v14/automation/clients/report/validate_failures.py b/automation/clients/report/validate_failures.py
index e99c9054..e99c9054 100755
--- a/v14/automation/clients/report/validate_failures.py
+++ b/automation/clients/report/validate_failures.py
diff --git a/v14/automation/common/__init__.py b/automation/common/__init__.py
index e69de29b..e69de29b 100644
--- a/v14/automation/common/__init__.py
+++ b/automation/common/__init__.py
diff --git a/v14/automation/common/command.py b/automation/common/command.py
index 205467cb..205467cb 100644
--- a/v14/automation/common/command.py
+++ b/automation/common/command.py
diff --git a/v14/automation/common/command_executer.py b/automation/common/command_executer.py
index 63e5af71..63e5af71 100644
--- a/v14/automation/common/command_executer.py
+++ b/automation/common/command_executer.py
diff --git a/v14/automation/common/command_executer_test.py b/automation/common/command_executer_test.py
index d3cef898..d3cef898 100755
--- a/v14/automation/common/command_executer_test.py
+++ b/automation/common/command_executer_test.py
diff --git a/v14/automation/common/events.py b/automation/common/events.py
index 79a69422..79a69422 100644
--- a/v14/automation/common/events.py
+++ b/automation/common/events.py
diff --git a/v14/automation/common/job.py b/automation/common/job.py
index 94cd6e2b..94cd6e2b 100644
--- a/v14/automation/common/job.py
+++ b/automation/common/job.py
diff --git a/v14/automation/common/job_group.py b/automation/common/job_group.py
index 6f9466b1..6f9466b1 100644
--- a/v14/automation/common/job_group.py
+++ b/automation/common/job_group.py
diff --git a/v14/automation/common/logger.py b/automation/common/logger.py
index 6bdd0c82..6bdd0c82 100644
--- a/v14/automation/common/logger.py
+++ b/automation/common/logger.py
diff --git a/v14/automation/common/machine.py b/automation/common/machine.py
index aa576c13..aa576c13 100644
--- a/v14/automation/common/machine.py
+++ b/automation/common/machine.py
diff --git a/v14/automation/common/machine_test.py b/automation/common/machine_test.py
index 0d5f32c7..0d5f32c7 100755
--- a/v14/automation/common/machine_test.py
+++ b/automation/common/machine_test.py
diff --git a/v14/automation/common/state_machine.py b/automation/common/state_machine.py
index d97f0fde..d97f0fde 100644
--- a/v14/automation/common/state_machine.py
+++ b/automation/common/state_machine.py
diff --git a/v14/automation/server/__init__.py b/automation/server/__init__.py
index e69de29b..e69de29b 100644
--- a/v14/automation/server/__init__.py
+++ b/automation/server/__init__.py
diff --git a/v14/automation/server/job_executer.py b/automation/server/job_executer.py
index 33080e84..33080e84 100644
--- a/v14/automation/server/job_executer.py
+++ b/automation/server/job_executer.py
diff --git a/v14/automation/server/job_group_manager.py b/automation/server/job_group_manager.py
index 56af1985..56af1985 100644
--- a/v14/automation/server/job_group_manager.py
+++ b/automation/server/job_group_manager.py
diff --git a/v14/automation/server/job_manager.py b/automation/server/job_manager.py
index a858b0de..a858b0de 100644
--- a/v14/automation/server/job_manager.py
+++ b/automation/server/job_manager.py
diff --git a/v14/automation/server/machine_manager.py b/automation/server/machine_manager.py
index 615b22b4..615b22b4 100644
--- a/v14/automation/server/machine_manager.py
+++ b/automation/server/machine_manager.py
diff --git a/v14/automation/server/machine_manager_test.py b/automation/server/machine_manager_test.py
index d84607b1..d84607b1 100755
--- a/v14/automation/server/machine_manager_test.py
+++ b/automation/server/machine_manager_test.py
diff --git a/v14/automation/server/monitor/__init__.py b/automation/server/monitor/__init__.py
index e69de29b..e69de29b 100644
--- a/v14/automation/server/monitor/__init__.py
+++ b/automation/server/monitor/__init__.py
diff --git a/v14/automation/server/monitor/dashboard.py b/automation/server/monitor/dashboard.py
index 236b9cbc..236b9cbc 100644
--- a/v14/automation/server/monitor/dashboard.py
+++ b/automation/server/monitor/dashboard.py
diff --git a/v14/automation/server/monitor/manage.py b/automation/server/monitor/manage.py
index 047c90ee..047c90ee 100755
--- a/v14/automation/server/monitor/manage.py
+++ b/automation/server/monitor/manage.py
diff --git a/v14/automation/server/monitor/settings.py b/automation/server/monitor/settings.py
index e6b7e633..e6b7e633 100644
--- a/v14/automation/server/monitor/settings.py
+++ b/automation/server/monitor/settings.py
diff --git a/v14/automation/server/monitor/start.sh b/automation/server/monitor/start.sh
index 4fc53bef..4fc53bef 100755
--- a/v14/automation/server/monitor/start.sh
+++ b/automation/server/monitor/start.sh
diff --git a/v14/automation/server/monitor/static/style.css b/automation/server/monitor/static/style.css
index b571b059..b571b059 100644
--- a/v14/automation/server/monitor/static/style.css
+++ b/automation/server/monitor/static/style.css
diff --git a/v14/automation/server/monitor/templates/base.html b/automation/server/monitor/templates/base.html
index 95ffc222..95ffc222 100644
--- a/v14/automation/server/monitor/templates/base.html
+++ b/automation/server/monitor/templates/base.html
diff --git a/v14/automation/server/monitor/templates/job.html b/automation/server/monitor/templates/job.html
index 90acd969..90acd969 100644
--- a/v14/automation/server/monitor/templates/job.html
+++ b/automation/server/monitor/templates/job.html
diff --git a/v14/automation/server/monitor/templates/job_group.html b/automation/server/monitor/templates/job_group.html
index b6ed8ea8..b6ed8ea8 100644
--- a/v14/automation/server/monitor/templates/job_group.html
+++ b/automation/server/monitor/templates/job_group.html
diff --git a/v14/automation/server/monitor/templates/job_group_list.html b/automation/server/monitor/templates/job_group_list.html
index b82fa730..b82fa730 100644
--- a/v14/automation/server/monitor/templates/job_group_list.html
+++ b/automation/server/monitor/templates/job_group_list.html
diff --git a/v14/automation/server/monitor/templates/job_log.html b/automation/server/monitor/templates/job_log.html
index 937b21b0..937b21b0 100644
--- a/v14/automation/server/monitor/templates/job_log.html
+++ b/automation/server/monitor/templates/job_log.html
diff --git a/v14/automation/server/monitor/templates/machine_list.html b/automation/server/monitor/templates/machine_list.html
index f81422d3..f81422d3 100644
--- a/v14/automation/server/monitor/templates/machine_list.html
+++ b/automation/server/monitor/templates/machine_list.html
diff --git a/v14/automation/server/monitor/templates/snippet_attribute_table.html b/automation/server/monitor/templates/snippet_attribute_table.html
index 24bacc17..24bacc17 100644
--- a/v14/automation/server/monitor/templates/snippet_attribute_table.html
+++ b/automation/server/monitor/templates/snippet_attribute_table.html
diff --git a/v14/automation/server/monitor/templates/snippet_code.html b/automation/server/monitor/templates/snippet_code.html
index 281754d6..281754d6 100644
--- a/v14/automation/server/monitor/templates/snippet_code.html
+++ b/automation/server/monitor/templates/snippet_code.html
diff --git a/v14/automation/server/monitor/templates/snippet_links.html b/automation/server/monitor/templates/snippet_links.html
index f19fa6e5..f19fa6e5 100644
--- a/v14/automation/server/monitor/templates/snippet_links.html
+++ b/automation/server/monitor/templates/snippet_links.html
diff --git a/v14/automation/server/monitor/urls.py b/automation/server/monitor/urls.py
index 80aa7d2a..80aa7d2a 100644
--- a/v14/automation/server/monitor/urls.py
+++ b/automation/server/monitor/urls.py
diff --git a/v14/automation/server/server.py b/automation/server/server.py
index ae761893..ae761893 100755
--- a/v14/automation/server/server.py
+++ b/automation/server/server.py
diff --git a/v14/automation/server/server_test.py b/automation/server/server_test.py
index 40cf491f..40cf491f 100755
--- a/v14/automation/server/server_test.py
+++ b/automation/server/server_test.py
diff --git a/v14/automation/server/test_pool.csv b/automation/server/test_pool.csv
index b0700c9b..b0700c9b 100644
--- a/v14/automation/server/test_pool.csv
+++ b/automation/server/test_pool.csv
diff --git a/v14/build-binutils/opts.sh b/build-binutils/opts.sh
index e69de29b..e69de29b 100644
--- a/v14/build-binutils/opts.sh
+++ b/build-binutils/opts.sh
diff --git a/v14/build-gcc/opts.sh b/build-gcc/opts.sh
index d1e6fadb..d1e6fadb 100644
--- a/v14/build-gcc/opts.sh
+++ b/build-gcc/opts.sh
diff --git a/v14/build_benchmarks.py b/build_benchmarks.py
index 41079f80..41079f80 100755
--- a/v14/build_benchmarks.py
+++ b/build_benchmarks.py
diff --git a/v14/build_chrome_browser.py b/build_chrome_browser.py
index f162c1d4..f162c1d4 100755
--- a/v14/build_chrome_browser.py
+++ b/build_chrome_browser.py
diff --git a/v14/build_chromeos.py b/build_chromeos.py
index 483e44a8..483e44a8 100755
--- a/v14/build_chromeos.py
+++ b/build_chromeos.py
diff --git a/v14/build_tc.py b/build_tc.py
index 0c009b3a..0c009b3a 100755
--- a/v14/build_tc.py
+++ b/build_tc.py
diff --git a/v14/command_executer_timeout_test.py b/command_executer_timeout_test.py
index 446651d3..446651d3 100755
--- a/v14/command_executer_timeout_test.py
+++ b/command_executer_timeout_test.py
diff --git a/v14/compare_benchmarks.py b/compare_benchmarks.py
index e63dfea7..e63dfea7 100755
--- a/v14/compare_benchmarks.py
+++ b/compare_benchmarks.py
diff --git a/v14/crb/autotest_gatherer.py b/crb/autotest_gatherer.py
index da39040d..da39040d 100644
--- a/v14/crb/autotest_gatherer.py
+++ b/crb/autotest_gatherer.py
diff --git a/v14/crb/autotest_run.py b/crb/autotest_run.py
index d6dc70f5..d6dc70f5 100644
--- a/v14/crb/autotest_run.py
+++ b/crb/autotest_run.py
diff --git a/v14/crb/crb_driver.py b/crb/crb_driver.py
index 6cf7af35..6cf7af35 100755
--- a/v14/crb/crb_driver.py
+++ b/crb/crb_driver.py
diff --git a/v14/crb/machine_manager_singleton.py b/crb/machine_manager_singleton.py
index 93629c4c..93629c4c 100644
--- a/v14/crb/machine_manager_singleton.py
+++ b/crb/machine_manager_singleton.py
diff --git a/v14/crb/table_formatter.py b/crb/table_formatter.py
index b3b82f09..b3b82f09 100644
--- a/v14/crb/table_formatter.py
+++ b/crb/table_formatter.py
diff --git a/v14/cros_login.py b/cros_login.py
index 44b22643..44b22643 100755
--- a/v14/cros_login.py
+++ b/cros_login.py
diff --git a/crosperf/benchmark.py b/crosperf/benchmark.py
index bc7f1fa8..8fe8a492 100644
--- a/crosperf/benchmark.py
+++ b/crosperf/benchmark.py
@@ -14,11 +14,13 @@ class Benchmark(object):
"""
def __init__(self, name, autotest_name, autotest_args, iterations,
- outlier_range, perf_args):
+ outlier_range, key_results_only, rm_chroot_tmp, perf_args):
self.name = name
self.autotest_name = autotest_name
self.autotest_args = autotest_args
self.iterations = iterations
self.outlier_range = outlier_range
self.perf_args = perf_args
+ self.key_results_only = key_results_only
+ self.rm_chroot_tmp = rm_chroot_tmp
self.iteration_adjusted = False
diff --git a/crosperf/benchmark_run.py b/crosperf/benchmark_run.py
index dc837937..80c95c4d 100644
--- a/crosperf/benchmark_run.py
+++ b/crosperf/benchmark_run.py
@@ -29,7 +29,8 @@ class BenchmarkRun(threading.Thread):
iteration,
cache_conditions,
machine_manager,
- logger_to_use):
+ logger_to_use,
+ share_users):
threading.Thread.__init__(self)
self.name = name
self._logger = logger_to_use
@@ -53,6 +54,7 @@ class BenchmarkRun(threading.Thread):
self._ce = command_executer.GetCommandExecuter(self._logger)
self.timeline = timeline.Timeline()
self.timeline.Record(STATUS_PENDING)
+ self.share_users = share_users
def run(self):
try:
@@ -67,7 +69,8 @@ class BenchmarkRun(threading.Thread):
self.label.board,
self.cache_conditions,
self._logger,
- self.label
+ self.label,
+ self.share_users
)
self.result = self.cache.ReadResult()
diff --git a/crosperf/benchmark_run_unittest.py b/crosperf/benchmark_run_unittest.py
index c4670c9c..47e027f4 100755
--- a/crosperf/benchmark_run_unittest.py
+++ b/crosperf/benchmark_run_unittest.py
@@ -19,14 +19,19 @@ from results_cache import MockResultsCache
class BenchmarkRunTest(unittest.TestCase):
def testDryRun(self):
my_label = MockLabel("test1", "image1", "/tmp/test_benchmark_run",
- "x86-alex", "chromeos-alex1", "")
- m = MockMachineManager("/tmp/chromeos_root")
+ "x86-alex", "chromeos-alex1",
+ image_args="",
+ image_md5sum="",
+ cache_dir="")
+ m = MockMachineManager("/tmp/chromeos_root", 0)
m.AddMachine("chromeos-alex1")
bench = Benchmark("PageCyler",
"Pyautoperf",
"",
1,
0.2,
+ False,
+ False,
"")
b = MockBenchmarkRun("test run",
bench,
@@ -34,7 +39,8 @@ class BenchmarkRunTest(unittest.TestCase):
1,
[],
m,
- logger.GetLogger())
+ logger.GetLogger(),
+ "")
b.cache = MockResultsCache()
b.autotest_runner = MockAutotestRunner()
b.start()
diff --git a/v14/crosperf/config.py b/crosperf/config.py
index 45a3d000..45a3d000 100644
--- a/v14/crosperf/config.py
+++ b/crosperf/config.py
diff --git a/crosperf/crosperf.py b/crosperf/crosperf.py
index cfb48d7c..cb7911fd 100755
--- a/crosperf/crosperf.py
+++ b/crosperf/crosperf.py
@@ -18,8 +18,6 @@ from utils import logger
import test_flag
-l = logger.GetLogger()
-
class MyIndentedHelpFormatter(optparse.IndentedHelpFormatter):
def format_description(self, description):
@@ -65,12 +63,20 @@ def Main(argv):
description=Help().GetHelp(),
formatter=MyIndentedHelpFormatter(),
version="%prog 0.1")
+
+ parser.add_option("-l", "--log_dir",
+ dest="log_dir",
+ default="",
+ help="The log_dir, default is under <crosperf_logs>/logs")
+
SetupParserOptions(parser)
options, args = parser.parse_args(argv)
# Convert the relevant options that are passed in into a settings
# object which will override settings in the experiment file.
option_settings = ConvertOptionsToSettings(options)
+ log_dir = os.path.abspath(os.path.expanduser(options.log_dir))
+ logger.GetLogger(log_dir)
if len(args) == 2:
experiment_filename = args[1]
@@ -87,7 +93,8 @@ def Main(argv):
experiment_name = os.path.basename(experiment_filename)
experiment_file.GetGlobalSettings().SetField("name", experiment_name)
experiment = ExperimentFactory().GetExperiment(experiment_file,
- working_directory)
+ working_directory,
+ log_dir)
atexit.register(Cleanup, experiment)
diff --git a/crosperf/experiment.py b/crosperf/experiment.py
index e9dc3d07..2a4590c4 100644
--- a/crosperf/experiment.py
+++ b/crosperf/experiment.py
@@ -9,23 +9,20 @@ import time
from utils import logger
-from autotest_runner import AutotestRunner
from benchmark_run import BenchmarkRun
from machine_manager import MachineManager
from machine_manager import MockMachineManager
-from results_cache import ResultsCache
-from results_report import HTMLResultsReport
import test_flag
class Experiment(object):
"""Class representing an Experiment to be run."""
- def __init__(self, name, remote, rerun_if_failed, working_directory,
+ def __init__(self, name, remote, working_directory,
chromeos_root, cache_conditions, labels, benchmarks,
- experiment_file, email_to):
+ experiment_file, email_to, acquire_timeout, log_dir,
+ share_users):
self.name = name
- self.rerun_if_failed = rerun_if_failed
self.working_directory = working_directory
self.remote = remote
self.chromeos_root = chromeos_root
@@ -34,11 +31,12 @@ class Experiment(object):
self.email_to = email_to
self.results_directory = os.path.join(self.working_directory,
self.name + "_results")
-
+ self.log_dir = log_dir
self.labels = labels
self.benchmarks = benchmarks
self.num_complete = 0
self.num_run_complete = 0
+ self.share_users = share_users
# We need one chromeos_root to run the benchmarks in, but it doesn't
# matter where it is, unless the ABIs are different.
@@ -51,10 +49,10 @@ class Experiment(object):
"the image path.")
if test_flag.GetTestMode():
- self.machine_manager = MockMachineManager(chromeos_root)
+ self.machine_manager = MockMachineManager(chromeos_root, acquire_timeout)
else:
- self.machine_manager = MachineManager(chromeos_root)
- self.l = logger.GetLogger()
+ self.machine_manager = MachineManager(chromeos_root, acquire_timeout)
+ self.l = logger.GetLogger(log_dir)
for machine in remote:
self.machine_manager.AddMachine(machine)
@@ -75,7 +73,7 @@ class Experiment(object):
benchmark_run_name = "%s: %s (%s)" % (label.name, benchmark.name,
iteration)
full_name = "%s_%s_%s" % (label.name, benchmark.name, iteration)
- logger_to_use = logger.Logger(os.path.dirname(__file__),
+ logger_to_use = logger.Logger(self.log_dir,
"run.%s" % (full_name),
True)
benchmark_run = BenchmarkRun(benchmark_run_name,
@@ -84,7 +82,8 @@ class Experiment(object):
iteration,
self.cache_conditions,
self.machine_manager,
- logger_to_use)
+ logger_to_use,
+ self.share_users)
benchmark_runs.append(benchmark_run)
return benchmark_runs
diff --git a/crosperf/experiment_factory.py b/crosperf/experiment_factory.py
index bd3076dd..3c92ee3e 100644
--- a/crosperf/experiment_factory.py
+++ b/crosperf/experiment_factory.py
@@ -7,6 +7,7 @@ import os
import socket
from benchmark import Benchmark
+import config
from experiment import Experiment
from label import Label
from label import MockLabel
@@ -22,13 +23,18 @@ class ExperimentFactory(object):
of experiments could be produced.
"""
- def GetExperiment(self, experiment_file, working_directory):
+ def GetExperiment(self, experiment_file, working_directory, log_dir):
"""Construct an experiment from an experiment file."""
global_settings = experiment_file.GetGlobalSettings()
experiment_name = global_settings.GetField("name")
remote = global_settings.GetField("remote")
- rerun_if_failed = global_settings.GetField("rerun_if_failed")
chromeos_root = global_settings.GetField("chromeos_root")
+ rm_chroot_tmp = global_settings.GetField("rm_chroot_tmp")
+ key_results_only = global_settings.GetField("key_results_only")
+ acquire_timeout= global_settings.GetField("acquire_timeout")
+ cache_dir = global_settings.GetField("cache_dir")
+ config.AddConfig("no_email", global_settings.GetField("no_email"))
+ share_users = global_settings.GetField("share_users")
# Default cache hit conditions. The image checksum in the cache and the
# computed checksum of the image must match. Also a cache file must exist.
@@ -55,8 +61,13 @@ class ExperimentFactory(object):
iterations = benchmark_settings.GetField("iterations")
outlier_range = benchmark_settings.GetField("outlier_range")
perf_args = benchmark_settings.GetField("perf_args")
+ rm_chroot_tmp = benchmark_settings.GetField("rm_chroot_tmp")
+ key_results_only = benchmark_settings.GetField("key_results_only")
+
benchmark = Benchmark(benchmark_name, autotest_name, autotest_args,
- iterations, outlier_range, perf_args)
+ iterations, outlier_range,
+ key_results_only, rm_chroot_tmp,
+ perf_args)
benchmarks.append(benchmark)
# Construct labels.
@@ -69,6 +80,8 @@ class ExperimentFactory(object):
chromeos_root = label_settings.GetField("chromeos_root")
board = label_settings.GetField("board")
my_remote = label_settings.GetField("remote")
+ image_md5sum = label_settings.GetField("md5sum")
+ cache_dir = label_settings.GetField("cache_dir")
# TODO(yunlian): We should consolidate code in machine_manager.py
# to derermine whether we are running from within google or not
if ("corp.google.com" in socket.gethostname() and
@@ -83,19 +96,19 @@ class ExperimentFactory(object):
image_args = label_settings.GetField("image_args")
if test_flag.GetTestMode():
label = MockLabel(label_name, image, chromeos_root, board, my_remote,
- image_args)
+ image_args, image_md5sum, cache_dir)
else:
label = Label(label_name, image, chromeos_root, board, my_remote,
- image_args)
+ image_args, image_md5sum, cache_dir)
labels.append(label)
email = global_settings.GetField("email")
all_remote = list(set(all_remote))
- experiment = Experiment(experiment_name, all_remote, rerun_if_failed,
+ experiment = Experiment(experiment_name, all_remote,
working_directory, chromeos_root,
cache_conditions, labels, benchmarks,
experiment_file.Canonicalize(),
- email)
+ email, acquire_timeout, log_dir, share_users)
return experiment
diff --git a/crosperf/experiment_factory_unittest.py b/crosperf/experiment_factory_unittest.py
index fa943519..6cee6b74 100755
--- a/crosperf/experiment_factory_unittest.py
+++ b/crosperf/experiment_factory_unittest.py
@@ -32,7 +32,9 @@ EXPERIMENT_FILE_1 = """
class ExperimentFactoryTest(unittest.TestCase):
def testLoadExperimentFile1(self):
experiment_file = ExperimentFile(StringIO.StringIO(EXPERIMENT_FILE_1))
- experiment = ExperimentFactory().GetExperiment(experiment_file, "")
+ experiment = ExperimentFactory().GetExperiment(experiment_file,
+ working_directory="",
+ log_dir="")
self.assertEqual(experiment.remote, ["chromeos-alex3"])
self.assertEqual(len(experiment.benchmarks), 1)
diff --git a/crosperf/experiment_runner.py b/crosperf/experiment_runner.py
index b905bbdc..9212ba56 100644
--- a/crosperf/experiment_runner.py
+++ b/crosperf/experiment_runner.py
@@ -12,6 +12,7 @@ from utils import logger
from utils.email_sender import EmailSender
from utils.file_utils import FileUtils
+import config
from experiment_status import ExperimentStatus
from results_report import HTMLResultsReport
from results_report import TextResultsReport
@@ -25,7 +26,7 @@ class ExperimentRunner(object):
def __init__(self, experiment):
self._experiment = experiment
- self.l = logger.GetLogger()
+ self.l = logger.GetLogger(experiment.log_dir)
self._ce = command_executer.GetCommandExecuter(self.l)
self._terminated = False
@@ -58,7 +59,8 @@ class ExperimentRunner(object):
if not benchmark_run.cache_hit:
send_mail = True
break
- if not send_mail and not experiment.email_to:
+ if (not send_mail and not experiment.email_to
+ or config.GetConfig("no_email")):
return
label_names = []
@@ -100,7 +102,7 @@ class ExperimentRunner(object):
benchmark_run_path = os.path.join(results_directory,
benchmark_run_name)
benchmark_run.result.CopyResultsTo(benchmark_run_path)
- benchmark_run.result.CleanUp()
+ benchmark_run.result.CleanUp(benchmark_run.benchmark.rm_chroot_tmp)
def Run(self):
self._Run(self._experiment)
diff --git a/crosperf/image_checksummer.py b/crosperf/image_checksummer.py
index f75dc944..dcc1cb02 100644
--- a/crosperf/image_checksummer.py
+++ b/crosperf/image_checksummer.py
@@ -2,24 +2,38 @@
# Copyright 2011 Google Inc. All Rights Reserved.
+import os
import threading
+
from utils import logger
from utils.file_utils import FileUtils
class ImageChecksummer(object):
class PerImageChecksummer(object):
- def __init__(self, filename):
+ def __init__(self, label):
self._lock = threading.Lock()
- self.filename = filename
+ self.label = label
self._checksum = None
def Checksum(self):
with self._lock:
if not self._checksum:
- logger.GetLogger().LogOutput("Computing checksum for '%s'." %
- self.filename)
- self._checksum = FileUtils().Md5File(self.filename)
+ logger.GetLogger().LogOutput("Acquiring checksum for '%s'." %
+ self.label.name)
+ self._checksum = None
+ if self.label.chromeos_image:
+ if os.path.exists(self.label.chromeos_image):
+ self._checksum = FileUtils().Md5File(self.label.chromeos_image)
+ logger.GetLogger().LogOutput("Computed checksum is "
+ ": %s" % self._checksum)
+ if not self._checksum:
+ if self.label.image_md5sum:
+ self._checksum = self.label.image_md5sum
+ logger.GetLogger().LogOutput("Checksum in experiment file is "
+ ": %s" % self._checksum)
+ else:
+ raise Exception("Checksum computing error.")
logger.GetLogger().LogOutput("Checksum is: %s" % self._checksum)
return self._checksum
@@ -34,16 +48,16 @@ class ImageChecksummer(object):
*args, **kwargs)
return cls._instance
- def Checksum(self, filename):
+ def Checksum(self, label):
with self._lock:
- if filename not in self._per_image_checksummers:
- self._per_image_checksummers[filename] = (ImageChecksummer.
- PerImageChecksummer(filename))
- checksummer = self._per_image_checksummers[filename]
+ if label.name not in self._per_image_checksummers:
+ self._per_image_checksummers[label.name] = (ImageChecksummer.
+ PerImageChecksummer(label))
+ checksummer = self._per_image_checksummers[label.name]
try:
return checksummer.Checksum()
except Exception, e:
- logger.GetLogger().LogError("Could not compute checksum of file '%s'."
- % filename)
+ logger.GetLogger().LogError("Could not compute checksum of image in label"
+ " '%s'."% label.name)
raise e
diff --git a/crosperf/label.py b/crosperf/label.py
index 64ce352f..be7a868e 100644
--- a/crosperf/label.py
+++ b/crosperf/label.py
@@ -10,7 +10,7 @@ from utils.file_utils import FileUtils
class Label(object):
def __init__(self, name, chromeos_image, chromeos_root, board, remote,
- image_args):
+ image_args, image_md5sum, cache_dir):
# Expand ~
chromeos_root = os.path.expanduser(chromeos_root)
chromeos_image = os.path.expanduser(chromeos_image)
@@ -20,6 +20,8 @@ class Label(object):
self.board = board
self.remote = remote
self.image_args = image_args
+ self.image_md5sum = image_md5sum
+ self.cache_dir = cache_dir
if not chromeos_root:
chromeos_root = FileUtils().ChromeOSRootFromImage(chromeos_image)
@@ -38,13 +40,15 @@ class Label(object):
class MockLabel(object):
def __init__(self, name, chromeos_image, chromeos_root, board, remote,
- image_args):
+ image_args, image_md5sum, cache_dir):
self.name = name
self.chromeos_image = chromeos_image
self.board = board
self.remote = remote
+ self.cache_dir = cache_dir
if not chromeos_root:
self.chromeos_root = "/tmp/chromeos_root"
else:
self.chromeos_root = chromeos_root
self.image_args = image_args
+ self.image_md5sum = image_md5sum
diff --git a/crosperf/machine_manager.py b/crosperf/machine_manager.py
index 9eb9bcdf..29a4df7a 100644
--- a/crosperf/machine_manager.py
+++ b/crosperf/machine_manager.py
@@ -111,12 +111,12 @@ class CrosMachine(object):
def _GetMachineID(self):
ce = command_executer.GetCommandExecuter()
- command = "ifconfig"
+ command = "dump_vpd_log --full --stdout"
ret, if_out, _ = ce.CrosRunCommand(
command, return_output=True,
machine=self.name, chromeos_root=self.chromeos_root)
b = if_out.splitlines()
- a = [l for l in b if "lan" in l]
+ a = [l for l in b if "Product" in l]
self.machine_id = a[0]
assert ret == 0, "Could not get machine_id from machine: %s" % self.name
@@ -131,7 +131,7 @@ class CrosMachine(object):
class MachineManager(object):
- def __init__(self, chromeos_root):
+ def __init__(self, chromeos_root, acquire_timeout):
self._lock = threading.RLock()
self._all_machines = []
self._machines = []
@@ -140,6 +140,7 @@ class MachineManager(object):
self.chromeos_root = None
self.machine_checksum = {}
self.machine_checksum_string = {}
+ self.acquire_timeout = acquire_timeout
if os.path.isdir(lock_machine.Machine.LOCKS_DIR):
self.no_lock = False
@@ -149,7 +150,7 @@ class MachineManager(object):
self.chromeos_root = chromeos_root
def ImageMachine(self, machine, label):
- checksum = ImageChecksummer().Checksum(label.chromeos_image)
+ checksum = ImageChecksummer().Checksum(label)
if machine.checksum == checksum:
return
chromeos_root = label.chromeos_root
@@ -193,8 +194,8 @@ class MachineManager(object):
with self._lock:
assert cros_machine, "Machine can't be None"
for m in self._machines:
- assert m.name != cros_machine.name, (
- "Tried to double-lock %s" % cros_machine.name)
+ if m.name == cros_machine.name:
+ return
if self.no_lock:
locked = True
else:
@@ -226,25 +227,33 @@ class MachineManager(object):
return len(set(checksums)) == 1
def AcquireMachine(self, chromeos_image, label):
- image_checksum = ImageChecksummer().Checksum(chromeos_image)
+ image_checksum = ImageChecksummer().Checksum(label)
machines = self.GetMachines(label)
+ check_interval_time = 120
with self._lock:
# Lazily external lock machines
-
- for m in machines:
- if m not in self._initialized_machines:
- self._initialized_machines.append(m)
+ while self.acquire_timeout >= 0:
+ for m in machines:
+ new_machine = m not in self._all_machines
self._TryToLockMachine(m)
- m.released_time = time.time()
- if not self.AreAllMachineSame(label):
- logger.GetLogger().LogFatal("-- not all the machine are identical")
- if not self.GetAvailableMachines(label):
+ if new_machine:
+ m.released_time = time.time()
+ if not self.AreAllMachineSame(label):
+ logger.GetLogger().LogFatal("-- not all the machine are identical")
+ if self.GetAvailableMachines(label):
+ break
+ else:
+ sleep_time = max(1, min(self.acquire_timeout, check_interval_time))
+ time.sleep(sleep_time)
+ self.acquire_timeout -= sleep_time
+
+ if self.acquire_timeout < 0:
machine_names = []
for machine in machines:
machine_names.append(machine.name)
logger.GetLogger().LogFatal("Could not acquire any of the "
- "following machines: '%s'"
- % ", ".join(machine_names))
+ "following machines: '%s'"
+ % ", ".join(machine_names))
### for m in self._machines:
### if (m.locked and time.time() - m.released_time < 10 and
@@ -374,8 +383,8 @@ class MockCrosMachine(CrosMachine):
class MockMachineManager(MachineManager):
- def __init__(self, chromeos_root):
- super(MockMachineManager, self).__init__(chromeos_root)
+ def __init__(self, chromeos_root, acquire_timeout):
+ super(MockMachineManager, self).__init__(chromeos_root, acquire_timeout)
def _TryToLockMachine(self, cros_machine):
self._machines.append(cros_machine)
diff --git a/crosperf/machine_manager_unittest.py b/crosperf/machine_manager_unittest.py
index 98baf456..84266d5e 100755
--- a/crosperf/machine_manager_unittest.py
+++ b/crosperf/machine_manager_unittest.py
@@ -12,7 +12,7 @@ import machine_manager
class MyMachineManager(machine_manager.MachineManager):
def __init__(self, chromeos_root):
- super(MyMachineManager, self).__init__(chromeos_root)
+ super(MyMachineManager, self).__init__(chromeos_root, 0)
def _TryToLockMachine(self, cros_machine):
self._machines.append(cros_machine)
@@ -30,9 +30,11 @@ class MyMachineManager(machine_manager.MachineManager):
CHROMEOS_ROOT = "/tmp/chromeos-root"
MACHINE_NAMES = ["lumpy1", "lumpy2", "lumpy3", "daisy1", "daisy2"]
LABEL_LUMPY = label.MockLabel("lumpy", "image", CHROMEOS_ROOT, "lumpy",
- ["lumpy1", "lumpy2", "lumpy3", "lumpy4"], "")
+ ["lumpy1", "lumpy2", "lumpy3", "lumpy4"],
+ "", "", "")
LABEL_MIX = label.MockLabel("mix", "image", CHROMEOS_ROOT, "mix",
- ["daisy1", "daisy2", "lumpy3", "lumpy4"], "")
+ ["daisy1", "daisy2", "lumpy3", "lumpy4"],
+ "", "", "")
class MachineManagerTest(unittest.TestCase):
diff --git a/crosperf/perf_table.py b/crosperf/perf_table.py
index b3387ea8..3c8b88b8 100644
--- a/crosperf/perf_table.py
+++ b/crosperf/perf_table.py
@@ -7,6 +7,7 @@ import os
from utils import perf_diff
+
def ParsePerfReport(perf_file):
"""It should return a dict."""
@@ -22,9 +23,16 @@ class PerfTable(object):
self._label_names = label_names
self.perf_data = {}
self.GenerateData()
- # {benchmark:{perf_event1:[[{func1:number, func2:number},
- # {func1: number, func2: number}]], ...},
+
+ # {benchmark:{perf_event1:[[{func1:number, func2:number,
+ # rows_to_show: number}
+ # {func1: number, func2: number
+ # rows_to_show: number}]], ...},
# benchmark2:...}
+ # The rows_to_show is temp data recording how many
+ # rows have over 1% running time.
+ self.row_info = {}
+ self.GetRowsToShow()
def GenerateData(self):
for label in self._label_names:
@@ -39,9 +47,10 @@ class PerfTable(object):
def ReadPerfReport(self, perf_file, label, benchmark_name, iteration):
"""Add the data from one run to the dict."""
- if not os.path.isfile(perf_file):
- return
- perf_of_run = perf_diff.GetPerfDictFromReport(perf_file)
+ if os.path.isfile(perf_file):
+ perf_of_run = perf_diff.GetPerfDictFromReport(perf_file)
+ else:
+ perf_of_run = {}
if benchmark_name not in self.perf_data:
self.perf_data[benchmark_name] = {}
for event in perf_of_run:
@@ -55,4 +64,22 @@ class PerfTable(object):
data_for_label = ben_data[event][label_index]
while len(data_for_label) <= iteration:
data_for_label.append({})
- data_for_label[iteration] = perf_of_run[event]
+ if perf_of_run:
+ data_for_label[iteration] = perf_of_run[event]
+ else:
+ data_for_label[iteration] = {}
+
+ def GetRowsToShow(self):
+ for benchmark in self.perf_data:
+ if benchmark not in self.row_info:
+ self.row_info[benchmark] = {}
+ for event in self.perf_data[benchmark]:
+ rows = 0
+ for run in self.perf_data[benchmark][event]:
+ for iteration in run:
+ if perf_diff.ROWS_TO_SHOW in iteration:
+ rows = max(iteration[perf_diff.ROWS_TO_SHOW], rows)
+ # delete the temp data which stores how many rows of
+ # the perf data have over 1% running time.
+ del iteration[perf_diff.ROWS_TO_SHOW]
+ self.row_info[benchmark][event] = rows
diff --git a/crosperf/results_cache.py b/crosperf/results_cache.py
index c0600962..0357275d 100644
--- a/crosperf/results_cache.py
+++ b/crosperf/results_cache.py
@@ -15,7 +15,8 @@ from utils import misc
from image_checksummer import ImageChecksummer
-SCRATCH_DIR = "/home/%s/cros_scratch" % getpass.getuser()
+SCRATCH_BASE = "/home/%s/cros_scratch"
+SCRATCH_DIR = SCRATCH_BASE % getpass.getuser()
RESULTS_FILE = "results.txt"
MACHINE_FILE = "machine.txt"
AUTOTEST_TARBALL = "autotest.tbz2"
@@ -55,16 +56,18 @@ class Result(object):
self._CopyFilesTo(dest_dir, self.perf_report_files)
def _GetKeyvals(self):
- generate_test_report = os.path.join(self._chromeos_root,
- "src",
- "platform",
- "crostestutils",
- "utils_py",
- "generate_test_report.py")
- command = ("python %s --no-color --csv %s" %
- (generate_test_report,
- self.results_dir))
- [_, out, _] = self._ce.RunCommand(command, return_output=True)
+ results_in_chroot = os.path.join(self._chromeos_root,
+ "chroot", "tmp")
+ if not self._temp_dir:
+ self._temp_dir = tempfile.mkdtemp(dir=results_in_chroot)
+ command = "cp -r {0}/* {1}".format(self.results_dir, self._temp_dir)
+ self._ce.RunCommand(command)
+
+ command = ("python generate_test_report --no-color --csv %s" %
+ (os.path.join("/tmp", os.path.basename(self._temp_dir))))
+ [_, out, _] = self._ce.ChrootRunCommand(self._chromeos_root,
+ command,
+ return_output=True)
keyvals_dict = {}
for line in out.splitlines():
tokens = re.split("=|,", line)
@@ -177,7 +180,9 @@ class Result(object):
self.retval = pickle.load(f)
# Untar the tarball to a temporary directory
- self._temp_dir = tempfile.mkdtemp()
+ self._temp_dir = tempfile.mkdtemp(dir=os.path.join(self._chromeos_root,
+ "chroot", "tmp"))
+
command = ("cd %s && tar xf %s" %
(self._temp_dir,
os.path.join(cache_dir, AUTOTEST_TARBALL)))
@@ -189,24 +194,25 @@ class Result(object):
self.perf_report_files = self._GetPerfReportFiles()
self._ProcessResults()
- def CleanUp(self):
+ def CleanUp(self, rm_chroot_tmp):
+ if rm_chroot_tmp:
+ command = "rm -rf %s" % self.results_dir
+ self._ce.RunCommand(command)
if self._temp_dir:
command = "rm -rf %s" % self._temp_dir
self._ce.RunCommand(command)
def StoreToCacheDir(self, cache_dir, machine_manager):
# Create the dir if it doesn't exist.
- command = "mkdir -p %s" % cache_dir
- ret = self._ce.RunCommand(command)
- if ret:
- raise Exception("Could not create cache dir: %s" % cache_dir)
- # Store to the cache directory.
- with open(os.path.join(cache_dir, RESULTS_FILE), "w") as f:
+ temp_dir = tempfile.mkdtemp()
+
+ # Store to the temp directory.
+ with open(os.path.join(temp_dir, RESULTS_FILE), "w") as f:
pickle.dump(self.out, f)
pickle.dump(self.err, f)
pickle.dump(self.retval, f)
- tarball = os.path.join(cache_dir, AUTOTEST_TARBALL)
+ tarball = os.path.join(temp_dir, AUTOTEST_TARBALL)
command = ("cd %s && "
"tar "
"--exclude=var/spool "
@@ -218,9 +224,22 @@ class Result(object):
# Store machine info.
# TODO(asharif): Make machine_manager a singleton, and don't pass it into
# this function.
- with open(os.path.join(cache_dir, MACHINE_FILE), "w") as f:
+ with open(os.path.join(temp_dir, MACHINE_FILE), "w") as f:
f.write(machine_manager.machine_checksum_string[self.label_name])
+ if os.path.exists(cache_dir):
+ command = "rm -rf {0}".format(cache_dir)
+ self._ce.RunCommand(command)
+
+ command = "mkdir -p {0} && ".format(os.path.dirname(cache_dir))
+ command += "mv {0} {1}".format(temp_dir, cache_dir)
+ ret = self._ce.RunCommand(command)
+ if ret:
+ command = "rm -rf {0}".format(temp_dir)
+ self._ce.RunCommand(command)
+ raise Exception("Could not move dir %s to dir %s" %
+ (temp_dir, cache_dir))
+
@classmethod
def CreateFromRun(cls, logger, chromeos_root, board, label_name,
out, err, retval):
@@ -273,7 +292,7 @@ class ResultsCache(object):
def Init(self, chromeos_image, chromeos_root, autotest_name, iteration,
autotest_args, machine_manager, board, cache_conditions,
- logger_to_use, label):
+ logger_to_use, label, share_users):
self.chromeos_image = chromeos_image
self.chromeos_root = chromeos_root
self.autotest_name = autotest_name
@@ -285,10 +304,12 @@ class ResultsCache(object):
self._logger = logger_to_use
self._ce = command_executer.GetCommandExecuter(self._logger)
self.label = label
+ self.share_users = share_users
def _GetCacheDirForRead(self):
- glob_path = self._FormCacheDir(self._GetCacheKeyList(True))
- matching_dirs = glob.glob(glob_path)
+ matching_dirs = []
+ for glob_path in self._FormCacheDir(self._GetCacheKeyList(True)):
+ matching_dirs += glob.glob(glob_path)
if matching_dirs:
# Cache file found.
@@ -297,12 +318,21 @@ class ResultsCache(object):
return None
def _GetCacheDirForWrite(self):
- return self._FormCacheDir(self._GetCacheKeyList(False))
+ return self._FormCacheDir(self._GetCacheKeyList(False))[0]
def _FormCacheDir(self, list_of_strings):
cache_key = " ".join(list_of_strings)
cache_dir = misc.GetFilenameFromString(cache_key)
- cache_path = os.path.join(SCRATCH_DIR, cache_dir)
+ if self.label.cache_dir:
+ cache_home = os.path.abspath(os.path.expanduser(self.label.cache_dir))
+ cache_path = [os.path.join(cache_home, cache_dir)]
+ else:
+ cache_path = [os.path.join(SCRATCH_DIR, cache_dir)]
+
+ for i in [x.strip() for x in self.share_users.split(",")]:
+ path = SCRATCH_BASE % i
+ cache_path.append(os.path.join(path, cache_dir))
+
return cache_path
def _GetCacheKeyList(self, read):
@@ -313,7 +343,7 @@ class ResultsCache(object):
if read and CacheConditions.CHECKSUMS_MATCH not in self.cache_conditions:
checksum = "*"
else:
- checksum = ImageChecksummer().Checksum(self.chromeos_image)
+ checksum = ImageChecksummer().Checksum(self.label)
if read and CacheConditions.IMAGE_PATH_MATCH not in self.cache_conditions:
image_path_checksum = "*"
diff --git a/crosperf/results_organizer.py b/crosperf/results_organizer.py
index 810186b2..2e5c9296 100644
--- a/crosperf/results_organizer.py
+++ b/crosperf/results_organizer.py
@@ -19,6 +19,11 @@ class ResultOrganizer(object):
[
]}.
"""
+ key_filter = ["milliseconds_",
+ "retval",
+ "iterations",
+ "ms_",
+ "score_"]
def __init__(self, benchmark_runs, labels, benchmarks=None):
self.result = {}
@@ -43,7 +48,15 @@ class ResultOrganizer(object):
cur_dict = cur_table[index]
if not benchmark_run.result:
continue
+ benchmark = benchmark_run.benchmark
+ key_filter_on = (benchmark.key_results_only and
+ "PyAutoPerfTest" in benchmark.name + benchmark.autotest_name and
+ "perf." not in benchmark.autotest_args)
for autotest_key in benchmark_run.result.keyvals:
+ if (key_filter_on and
+ not any([key for key in self.key_filter if key in autotest_key])
+ ):
+ continue
result_value = benchmark_run.result.keyvals[autotest_key]
cur_dict[autotest_key] = result_value
self._DuplicatePass()
diff --git a/crosperf/results_report.py b/crosperf/results_report.py
index f7434132..61c67d5b 100644
--- a/crosperf/results_report.py
+++ b/crosperf/results_report.py
@@ -11,6 +11,7 @@ from perf_table import PerfTable
class ResultsReport(object):
MAX_COLOR_CODE = 255
+ PERF_ROWS = 5
def __init__(self, experiment):
self.experiment = experiment
@@ -40,7 +41,13 @@ class ResultsReport(object):
Column(AmeanResult(),
Format()),
Column(StdResult(),
- Format())
+ Format(), "StdDev"),
+ Column(CoeffVarResult(),
+ CoeffVarFormat(), "StdDev/Mean"),
+ Column(GmeanRatioResult(),
+ RatioFormat(), "GmeanSpeedup"),
+ Column(PValueResult(),
+ PValueFormat(), "p-value")
]
if not perf:
return self._GetTables(self.labels, self.benchmark_runs, columns)
@@ -138,10 +145,12 @@ class ResultsReport(object):
ben_table = self._GetTableHeader(ben)
tables.append(ben_table)
benchmark_data = p_table.perf_data[benchmark]
+ row_info = p_table.row_info[benchmark]
table = []
for event in benchmark_data:
- tg = TableGenerator(benchmark_data[event], label_names)
- table = tg.GetTable()
+ tg = TableGenerator(benchmark_data[event], label_names,
+ sort=TableGenerator.SORT_BY_VALUES_DESC)
+ table = tg.GetTable(max(self.PERF_ROWS, row_info[event]))
parsed_columns = self._ParseColumn(columns, ben.iterations)
tf = TableFormatter(table, parsed_columns)
tf.GenerateCellTable()
diff --git a/crosperf/settings_factory.py b/crosperf/settings_factory.py
index 11fa4b4b..924bc114 100644
--- a/crosperf/settings_factory.py
+++ b/crosperf/settings_factory.py
@@ -26,6 +26,12 @@ class BenchmarkSettings(Settings):
self.AddField(FloatField("outlier_range", default=0.2,
description="The percentage of highest/lowest "
"values to omit when computing the average."))
+ self.AddField(BooleanField("rm_chroot_tmp", default=False,
+ description="Whether remove the run_remote_test"
+ "result in the chroot"))
+ self.AddField(BooleanField("key_results_only", default=True,
+ description="Whether only show the key results"
+ "of pyautoperf"))
self.AddField(TextField("perf_args", default="",
description="The optional profile command. It "
"enables perf commands to record perforamance "
@@ -44,6 +50,8 @@ class LabelSettings(Settings):
"contains a src/scripts directory. Defaults to "
"the chromeos checkout which contains the "
"chromeos_image."))
+ self.AddField(TextField("md5sum", default="",
+ description="The md5sum of this image"))
self.AddField(TextField("board", required=True, description="The target "
"board for running experiments on, e.g. x86-alex."))
self.AddField(ListField("remote", description=
@@ -53,6 +61,8 @@ class LabelSettings(Settings):
default="",
description="Extra arguments to pass to "
"image_chromeos.py."))
+ self.AddField(TextField("cache_dir", default="",
+ description="The cache dir for this image."))
class GlobalSettings(Settings):
@@ -69,6 +79,9 @@ class GlobalSettings(Settings):
self.AddField(BooleanField("rerun_if_failed", description="Whether to "
"re-run failed autotest runs or not.",
default=False))
+ self.AddField(BooleanField("rm_chroot_tmp", default=False,
+ description="Whether remove the run_remote_test"
+ "result in the chroot"))
self.AddField(ListField("email", description="Space-seperated"
"list of email addresses to send email to."))
self.AddField(BooleanField("rerun", description="Whether to ignore the "
@@ -89,11 +102,27 @@ class GlobalSettings(Settings):
"contains a src/scripts directory. Defaults to "
"the chromeos checkout which contains the "
"chromeos_image."))
+ self.AddField(BooleanField("key_results_only", default=True,
+ description="Whether only show the key results"
+ "of pyautoperf"))
+ self.AddField(IntegerField("acquire_timeout", default=0,
+ description="Number of seconds to wait for "
+ "machine before exit if all the machines in "
+ "the experiment file are busy. Default is 0"))
self.AddField(TextField("perf_args", default="",
description="The optional profile command. It "
"enables perf commands to record perforamance "
"related counters. It must start with perf "
"command record or stat followed by arguments."))
+ self.AddField(TextField("cache_dir", default="",
+ description="The abs path of cache dir. "
+ "Default is /home/$(whoami)/cros_scratch."))
+ self.AddField(BooleanField("no_email", default=False,
+ description="Whether to disable the email to "
+ "user after crosperf finishes."))
+ self.AddField(TextField("share_users", default="",
+ description="Who's cache data you want to "
+ "use. It accepts multiple users seperated by \",\""))
class SettingsFactory(object):
diff --git a/v14/cwp/bartlett/app.yaml b/cwp/bartlett/app.yaml
index 60010f70..60010f70 100644
--- a/v14/cwp/bartlett/app.yaml
+++ b/cwp/bartlett/app.yaml
diff --git a/v14/cwp/bartlett/server.py b/cwp/bartlett/server.py
index 3e4f1be7..3e4f1be7 100755
--- a/v14/cwp/bartlett/server.py
+++ b/cwp/bartlett/server.py
diff --git a/v14/cwp/bartlett/static/favicon.ico b/cwp/bartlett/static/favicon.ico
index 19b58c2e..19b58c2e 100644
--- a/v14/cwp/bartlett/static/favicon.ico
+++ b/cwp/bartlett/static/favicon.ico
Binary files differ
diff --git a/v14/cwp/bartlett/test/server_tester.py b/cwp/bartlett/test/server_tester.py
index e5a2341d..e5a2341d 100644
--- a/v14/cwp/bartlett/test/server_tester.py
+++ b/cwp/bartlett/test/server_tester.py
diff --git a/v14/cwp/bartlett/update_appengine_server b/cwp/bartlett/update_appengine_server
index f3812057..f3812057 100755
--- a/v14/cwp/bartlett/update_appengine_server
+++ b/cwp/bartlett/update_appengine_server
diff --git a/v14/cwp/demo_pipeline.sh b/cwp/demo_pipeline.sh
index d45c5c44..d45c5c44 100644
--- a/v14/cwp/demo_pipeline.sh
+++ b/cwp/demo_pipeline.sh
diff --git a/v14/cwp/interpreter/app_engine_pull.py b/cwp/interpreter/app_engine_pull.py
index 65f67940..65f67940 100644
--- a/v14/cwp/interpreter/app_engine_pull.py
+++ b/cwp/interpreter/app_engine_pull.py
diff --git a/v14/cwp/interpreter/symbolizer.py b/cwp/interpreter/symbolizer.py
index 3e589538..3e589538 100644
--- a/v14/cwp/interpreter/symbolizer.py
+++ b/cwp/interpreter/symbolizer.py
diff --git a/v14/cwp/performance/experiment_gen.py b/cwp/performance/experiment_gen.py
index 7752c11e..7752c11e 100644
--- a/v14/cwp/performance/experiment_gen.py
+++ b/cwp/performance/experiment_gen.py
diff --git a/v14/dejagnu/__init__.py b/dejagnu/__init__.py
index e69de29b..e69de29b 100644
--- a/v14/dejagnu/__init__.py
+++ b/dejagnu/__init__.py
diff --git a/v14/dejagnu/boards/chromeos-machine.exp b/dejagnu/boards/chromeos-machine.exp
index b168b677..b168b677 100644
--- a/v14/dejagnu/boards/chromeos-machine.exp
+++ b/dejagnu/boards/chromeos-machine.exp
diff --git a/v14/dejagnu/chromeos.exp.in b/dejagnu/chromeos.exp.in
index 889653aa..889653aa 100644
--- a/v14/dejagnu/chromeos.exp.in
+++ b/dejagnu/chromeos.exp.in
diff --git a/v14/dejagnu/run_dejagnu.py b/dejagnu/run_dejagnu.py
index 8943bb20..8943bb20 100755
--- a/v14/dejagnu/run_dejagnu.py
+++ b/dejagnu/run_dejagnu.py
diff --git a/v14/dejagnu/site.exp b/dejagnu/site.exp
index beaa958d..beaa958d 100644
--- a/v14/dejagnu/site.exp
+++ b/dejagnu/site.exp
diff --git a/v14/fdo_scripts/divide_and_merge_profiles.py b/fdo_scripts/divide_and_merge_profiles.py
index c75e353a..c75e353a 100755
--- a/v14/fdo_scripts/divide_and_merge_profiles.py
+++ b/fdo_scripts/divide_and_merge_profiles.py
diff --git a/v14/fdo_scripts/divide_and_merge_profiles_test.py b/fdo_scripts/divide_and_merge_profiles_test.py
index f42db4e9..f42db4e9 100755
--- a/v14/fdo_scripts/divide_and_merge_profiles_test.py
+++ b/fdo_scripts/divide_and_merge_profiles_test.py
diff --git a/v14/fdo_scripts/profile_cycler.py b/fdo_scripts/profile_cycler.py
index efdafffa..efdafffa 100755
--- a/v14/fdo_scripts/profile_cycler.py
+++ b/fdo_scripts/profile_cycler.py
diff --git a/v14/fdo_scripts/summarize_hot_blocks.py b/fdo_scripts/summarize_hot_blocks.py
index c19f5477..c19f5477 100644
--- a/v14/fdo_scripts/summarize_hot_blocks.py
+++ b/fdo_scripts/summarize_hot_blocks.py
diff --git a/v14/fdo_scripts/vanilla_vs_fdo.py b/fdo_scripts/vanilla_vs_fdo.py
index 3cf5f4b6..3cf5f4b6 100644
--- a/v14/fdo_scripts/vanilla_vs_fdo.py
+++ b/fdo_scripts/vanilla_vs_fdo.py
diff --git a/v14/get_common_image_version.py b/get_common_image_version.py
index cdac8006..cdac8006 100755
--- a/v14/get_common_image_version.py
+++ b/get_common_image_version.py
diff --git a/image_chromeos.py b/image_chromeos.py
index 30b29a45..d5d5f7fe 100755
--- a/image_chromeos.py
+++ b/image_chromeos.py
@@ -171,6 +171,7 @@ def DoImage(argv):
options.remote)
logger.GetLogger().LogFatalIf(not successfully_imaged,
"Image verification failed!")
+ TryRemountPartitionAsRW(options.chromeos_root, options.remote)
else:
l.LogOutput("Checksums match. Skipping reimage")
return retval
@@ -268,6 +269,23 @@ def VerifyChromeChecksum(chromeos_root, image, remote):
else:
return False
+# Remount partition as writable.
+# TODO: auto-detect if an image is built using --noenable_rootfs_verification.
+def TryRemountPartitionAsRW(chromeos_root, remote):
+ l = logger.GetLogger()
+ cmd_executer = command_executer.GetCommandExecuter()
+ command = "sudo mount -o remount,rw /"
+ retval = cmd_executer.CrosRunCommand(\
+ command, chromeos_root=chromeos_root, machine=remote, terminated_timeout=10)
+ if retval:
+ ## Safely ignore.
+ l.LogWarning("Failed to remount partition as rw, "
+ "probably the image was not built with "
+ "\"--noenable_rootfs_verification\", "
+ "you can safely ignore this.")
+ else:
+ l.LogOutput("Re-mounted partition as writable.")
+
def EnsureMachineUp(chromeos_root, remote):
l = logger.GetLogger()
diff --git a/v14/lock_machine.py b/lock_machine.py
index 0f948c3d..0f948c3d 100755
--- a/v14/lock_machine.py
+++ b/lock_machine.py
diff --git a/v14/lock_machine_test.py b/lock_machine_test.py
index d61878b8..d61878b8 100644
--- a/v14/lock_machine_test.py
+++ b/lock_machine_test.py
diff --git a/v14/produce_output.py b/produce_output.py
index 0e982bf7..0e982bf7 100755
--- a/v14/produce_output.py
+++ b/produce_output.py
diff --git a/v14/pyrun b/pyrun
index d9f5d75a..d9f5d75a 100755
--- a/v14/pyrun
+++ b/pyrun
diff --git a/v14/remote_gcc_build.py b/remote_gcc_build.py
index b2dfee38..b2dfee38 100755
--- a/v14/remote_gcc_build.py
+++ b/remote_gcc_build.py
diff --git a/v14/remote_kill_test.py b/remote_kill_test.py
index e56ef209..e56ef209 100755
--- a/v14/remote_kill_test.py
+++ b/remote_kill_test.py
diff --git a/v14/remote_test.py b/remote_test.py
index 2ef27f9d..2ef27f9d 100755
--- a/v14/remote_test.py
+++ b/remote_test.py
diff --git a/v14/repo_to_repo.py b/repo_to_repo.py
index 88433dfe..88433dfe 100755
--- a/v14/repo_to_repo.py
+++ b/repo_to_repo.py
diff --git a/v14/repo_to_repo_files/binutils-master.rtr b/repo_to_repo_files/binutils-master.rtr
index 7cb31941..7cb31941 100644
--- a/v14/repo_to_repo_files/binutils-master.rtr
+++ b/repo_to_repo_files/binutils-master.rtr
diff --git a/v14/repo_to_repo_files/binutils-mobile_toolchain_v16.rtr b/repo_to_repo_files/binutils-mobile_toolchain_v16.rtr
index 51f73cb2..51f73cb2 100644
--- a/v14/repo_to_repo_files/binutils-mobile_toolchain_v16.rtr
+++ b/repo_to_repo_files/binutils-mobile_toolchain_v16.rtr
diff --git a/v14/repo_to_repo_files/crosperf.rtr b/repo_to_repo_files/crosperf.rtr
index 0efb1cde..0efb1cde 100644
--- a/v14/repo_to_repo_files/crosperf.rtr
+++ b/repo_to_repo_files/crosperf.rtr
diff --git a/v14/repo_to_repo_files/gcc-branches_google_4_7.rtr b/repo_to_repo_files/gcc-branches_google_4_7.rtr
index ec7fcf34..ec7fcf34 100644
--- a/v14/repo_to_repo_files/gcc-branches_google_4_7.rtr
+++ b/repo_to_repo_files/gcc-branches_google_4_7.rtr
diff --git a/v14/repo_to_repo_files/gcc-branches_google_main.rtr b/repo_to_repo_files/gcc-branches_google_main.rtr
index 289f531b..289f531b 100644
--- a/v14/repo_to_repo_files/gcc-branches_google_main.rtr
+++ b/repo_to_repo_files/gcc-branches_google_main.rtr
diff --git a/v14/repo_to_repo_files/gcc-master.rtr b/repo_to_repo_files/gcc-master.rtr
index 82a91c01..82a91c01 100644
--- a/v14/repo_to_repo_files/gcc-master.rtr
+++ b/repo_to_repo_files/gcc-master.rtr
diff --git a/v14/repo_to_repo_files/gdb-master.rtr b/repo_to_repo_files/gdb-master.rtr
index c29e36e0..c29e36e0 100644
--- a/v14/repo_to_repo_files/gdb-master.rtr
+++ b/repo_to_repo_files/gdb-master.rtr
diff --git a/v14/repo_to_repo_files/toolchain-utils.rtr b/repo_to_repo_files/toolchain-utils.rtr
index 09a74730..09a74730 100644
--- a/v14/repo_to_repo_files/toolchain-utils.rtr
+++ b/repo_to_repo_files/toolchain-utils.rtr
diff --git a/v14/report_generator.py b/report_generator.py
index a5f11ca6..a5f11ca6 100755
--- a/v14/report_generator.py
+++ b/report_generator.py
diff --git a/v14/run_benchmarks.py b/run_benchmarks.py
index 9dc49004..9dc49004 100755
--- a/v14/run_benchmarks.py
+++ b/run_benchmarks.py
diff --git a/v14/run_tests.py b/run_tests.py
index 075f29b1..075f29b1 100755
--- a/v14/run_tests.py
+++ b/run_tests.py
diff --git a/v14/setup_chromeos.py b/setup_chromeos.py
index 7d3c22da..7d3c22da 100755
--- a/v14/setup_chromeos.py
+++ b/setup_chromeos.py
diff --git a/v14/sheriff_rotation.py b/sheriff_rotation.py
index 4ccf896d..4ccf896d 100755
--- a/v14/sheriff_rotation.py
+++ b/sheriff_rotation.py
diff --git a/v14/summarize_results.py b/summarize_results.py
index 3e561f3b..3e561f3b 100755
--- a/v14/summarize_results.py
+++ b/summarize_results.py
diff --git a/v14/tc_enter_chroot.py b/tc_enter_chroot.py
index 50eb312c..50eb312c 100755
--- a/v14/tc_enter_chroot.py
+++ b/tc_enter_chroot.py
diff --git a/v14/test_gcc_dejagnu.py b/test_gcc_dejagnu.py
index 0edf2cb9..0edf2cb9 100755
--- a/v14/test_gcc_dejagnu.py
+++ b/test_gcc_dejagnu.py
diff --git a/v14/test_toolchains.py b/test_toolchains.py
index 18448ab2..18448ab2 100644
--- a/v14/test_toolchains.py
+++ b/test_toolchains.py
diff --git a/v14/utils/buildbot_json.py b/utils/buildbot_json.py
index 6ea7f8fb..6ea7f8fb 100755
--- a/v14/utils/buildbot_json.py
+++ b/utils/buildbot_json.py
diff --git a/utils/command_executer.py b/utils/command_executer.py
index 3edb6262..0aedc47c 100644
--- a/utils/command_executer.py
+++ b/utils/command_executer.py
@@ -74,11 +74,14 @@ class CommandExecuter:
out = err = None
pipes = [p.stdout, p.stderr]
+ my_poll = select.poll()
+ my_poll.register(p.stdout, select.POLLIN)
+ my_poll.register(p.stderr, select.POLLIN)
+
terminated_time = None
started_time = time.time()
while len(pipes):
- fds = select.select(pipes, [], [], 0.1)
if command_terminator and command_terminator.IsTerminated():
self.RunCommand("sudo kill -9 " + str(p.pid),
print_to_console=print_to_console)
@@ -88,21 +91,25 @@ class CommandExecuter:
return (p.wait, full_stdout, full_stderr)
else:
return wait
- for fd in fds[0]:
- if fd == p.stdout:
+
+ l=my_poll.poll(100)
+ for (fd, evt) in l:
+ if fd == p.stdout.fileno():
out = os.read(p.stdout.fileno(), 16384)
if return_output:
full_stdout += out
self.logger.LogCommandOutput(out, print_to_console)
if out == "":
pipes.remove(p.stdout)
- if fd == p.stderr:
+ my_poll.unregister(p.stdout)
+ if fd == p.stderr.fileno():
err = os.read(p.stderr.fileno(), 16384)
if return_output:
full_stderr += err
self.logger.LogCommandError(err, print_to_console)
if err == "":
pipes.remove(p.stderr)
+ my_poll.unregister(p.stderr)
if p.poll() is not None:
if terminated_time is None:
diff --git a/v14/utils/command_executer_unittest.py b/utils/command_executer_unittest.py
index ea0e918c..ea0e918c 100755
--- a/v14/utils/command_executer_unittest.py
+++ b/utils/command_executer_unittest.py
diff --git a/utils/logger.py b/utils/logger.py
index faad9666..99c679ab 100644
--- a/utils/logger.py
+++ b/utils/logger.py
@@ -167,17 +167,19 @@ class Logger(object):
main_logger = None
-def InitLogger(script_name, print_console=True):
+def InitLogger(script_name, log_dir, print_console=True):
"""Initialize a global logger. To be called only once."""
global main_logger
assert not main_logger, "The logger has already been initialized"
rootdir, basefilename = GetRoot(script_name)
- main_logger = Logger(rootdir, basefilename, print_console)
+ if not log_dir:
+ log_dir = rootdir
+ main_logger = Logger(log_dir, basefilename, print_console)
-def GetLogger():
+def GetLogger(log_dir=""):
if not main_logger:
- InitLogger(sys.argv[0])
+ InitLogger(sys.argv[0], log_dir)
return main_logger
diff --git a/utils/misc.py b/utils/misc.py
index 40622512..175a6e07 100644
--- a/utils/misc.py
+++ b/utils/misc.py
@@ -145,19 +145,25 @@ def DoesLabelExist(chromeos_root, board, label):
return os.path.exists(image_label)
-def GetBuildPackagesCommand(board, usepkg=False):
+def GetBuildPackagesCommand(board, usepkg=False, debug=False):
if usepkg:
usepkg_flag = "--usepkg"
else:
usepkg_flag = "--nousepkg"
+ if debug:
+ withdebug_flag = '--withdebug'
+ else:
+ withdebug_flag = '--nowithdebug'
return ("./build_packages %s --withdev --withtest --withautotest "
- "--skip_toolchain_update --nowithdebug --board=%s" %
- (usepkg_flag, board))
-
+ "--skip_toolchain_update %s --board=%s" %
+ (usepkg_flag, withdebug_flag, board))
-def GetBuildImageCommand(board):
- return "./build_image --board=%s test" % board
+def GetBuildImageCommand(board, dev=False):
+ dev_args = ""
+ if dev:
+ dev_args = "--noenable_rootfs_verification --disk_layout=2gb-rootfs"
+ return "./build_image --board=%s %s test" % (board, dev_args)
def GetSetupBoardCommand(board, gcc_version=None, binutils_version=None,
usepkg=None, force=None):
@@ -252,14 +258,17 @@ def AcquireLock(lock_file, timeout=1200):
abs_path = os.path.abspath(lock_file)
dir_path = os.path.dirname(abs_path)
sleep_time = min(10, timeout/10.0)
+ reason = "pid: {0}, commad: {1}".format(os.getpid(),
+ sys.argv[0])
if not os.path.exists(dir_path):
try:
- os.makedirs(dir_path)
+ with lock_machine.FileCreationMask(0002):
+ os.makedirs(dir_path)
except OSError:
print "Cannot create dir {0}, exiting...".format(dir_path)
exit(0)
while True:
- locked = (lock_machine.Lock(lock_file).NonBlockingLock(True, sys.argv[0]))
+ locked = (lock_machine.Lock(lock_file).NonBlockingLock(True, reason))
if locked:
break
time.sleep(sleep_time)
diff --git a/utils/perf_diff.py b/utils/perf_diff.py
index cfe90a9b..d56eba16 100755
--- a/utils/perf_diff.py
+++ b/utils/perf_diff.py
@@ -15,16 +15,20 @@ import sys
import misc
import tabulator
+ROWS_TO_SHOW = "Rows_to_show_in_the_perf_table"
-def GetPerfDictFromReport(report_file, num_functions=5):
+def GetPerfDictFromReport(report_file):
output = {}
perf_report = PerfReport(report_file)
for k, v in perf_report.sections.items():
if k not in output:
output[k] = {}
- for function in v.functions[:num_functions]:
+ output[k][ROWS_TO_SHOW] = 0
+ for function in v.functions:
out_key = "%s" % (function.name)
output[k][out_key] = function.count
+ if function.percent > 1:
+ output[k][ROWS_TO_SHOW] += 1
return output
@@ -85,6 +89,7 @@ class Function(object):
def __init__(self):
self.count = 0
self.name = ""
+ self.percent = 0
class Section(object):
@@ -110,6 +115,7 @@ class Section(object):
if not line.startswith("#"):
fields = [f for f in line.split(" ") if f]
function = Function()
+ function.percent = float(fields[0].strip("%"))
function.count = int(fields[1])
function.name = " ".join(fields[2:])
self.functions.append(function)
@@ -164,7 +170,7 @@ class PerfReport(object):
def _SplitSections(self):
self._section_contents = []
- indices = [m.start() for m in re.finditer("Events:", self._perf_contents)]
+ indices = [m.start() for m in re.finditer("# Events:", self._perf_contents)]
indices.append(len(self._perf_contents))
for i in range(len(indices) - 1):
section_content = self._perf_contents[indices[i]:indices[i+1]]
diff --git a/utils/tabulator.py b/utils/tabulator.py
index ed83a04b..f75419ab 100644
--- a/utils/tabulator.py
+++ b/utils/tabulator.py
@@ -2,8 +2,69 @@
# Copyright 2011 Google Inc. All Rights Reserved.
+"""Table generating, analyzing and printing functions.
+
+This defines several classes that are used to generate, analyze and print
+tables.
+
+Example usage:
+
+ from utils import tabulator
+
+ data = [["benchmark1", "33", "44"],["benchmark2", "44", "33"]]
+ tabulator.GetSimpleTable(data)
+
+You could also use it to generate more complex tables with analysis such as
+p-values, custom colors, etc. Tables are generated by TableGenerator and
+analyzed/formatted by TableFormatter. TableFormatter can take in a list of
+columns with custom result computation and coloring, and will compare values in
+each row according to taht scheme. Here is a complex example on printing a
+table:
+
+ from utils import tabulator
+
+ runs = [[{"k1": "10", "k2": "12", "k5": "40", "k6": "40",
+ "ms_1": "20", "k7": "FAIL", "k8": "PASS", "k9": "PASS",
+ "k10": "0"},
+ {"k1": "13", "k2": "14", "k3": "15", "ms_1": "10", "k8": "PASS",
+ "k9": "FAIL", "k10": "0"}],
+ [{"k1": "50", "k2": "51", "k3": "52", "k4": "53", "k5": "35", "k6":
+ "45", "ms_1": "200", "ms_2": "20", "k7": "FAIL", "k8": "PASS", "k9":
+ "PASS"}]]
+ labels = ["vanilla", "modified"]
+ tg = TableGenerator(runs, labels, TableGenerator.SORT_BY_VALUES_DESC)
+ table = tg.GetTable()
+ columns = [Column(LiteralResult(),
+ Format(),
+ "Literal"),
+ Column(AmeanResult(),
+ Format()),
+ Column(StdResult(),
+ Format()),
+ Column(CoeffVarResult(),
+ CoeffVarFormat()),
+ Column(NonEmptyCountResult(),
+ Format()),
+ Column(AmeanRatioResult(),
+ PercentFormat()),
+ Column(AmeanRatioResult(),
+ RatioFormat()),
+ Column(GmeanRatioResult(),
+ RatioFormat()),
+ Column(PValueResult(),
+ PValueFormat()),
+ ]
+ tf = TableFormatter(table, columns)
+ cell_table = tf.GetCellTable()
+ tp = TablePrinter(cell_table, out_to)
+ print tp.Print()
+
+"""
+
+
import getpass
import math
+import sys
import numpy
import colortrans
@@ -58,8 +119,10 @@ class TableGenerator(object):
for run in run_list:
if key in run:
values.append(run[key])
- ret = max(_StripNone(values))
- return ret
+ values = _StripNone(values)
+ if _AllFloat(values):
+ values = _GetFloats(values)
+ return max(values)
def _GetLowestValue(self, key):
values = []
@@ -67,15 +130,19 @@ class TableGenerator(object):
for run in run_list:
if key in run:
values.append(run[key])
- ret = min(_StripNone(values))
- return ret
+ values = _StripNone(values)
+ if _AllFloat(values):
+ values = _GetFloats(values)
+ return min(values)
def _SortKeys(self, keys):
if self._sort == self.SORT_BY_KEYS:
return sorted(keys)
elif self._sort == self.SORT_BY_VALUES:
+ # pylint: disable=unnecessary-lambda
return sorted(keys, key=lambda x: self._GetLowestValue(x))
elif self._sort == self.SORT_BY_VALUES_DESC:
+ # pylint: disable=unnecessary-lambda
return sorted(keys, key=lambda x: self._GetHighestValue(x), reverse=True)
else:
assert 0, "Unimplemented sort %s" % self._sort
@@ -84,7 +151,7 @@ class TableGenerator(object):
keys = self._AggregateKeys()
return self._SortKeys(keys)
- def GetTable(self):
+ def GetTable(self, number_of_rows=sys.maxint):
"""Returns a table from a list of list of dicts.
The list of list of dicts is passed into the constructor of TableGenerator.
@@ -92,7 +159,7 @@ class TableGenerator(object):
table of values.
Args:
- None
+ number_of_rows: Maximum number of rows to return from the table.
Returns:
A list of lists which is the table.
@@ -113,6 +180,7 @@ class TableGenerator(object):
keys = self._GetKeys()
header = [self._key_name] + self._labels
table = [header]
+ rows = 0
for k in keys:
row = [k]
for run_list in self._runs:
@@ -124,6 +192,9 @@ class TableGenerator(object):
v.append(None)
row.append(v)
table.append(row)
+ rows += 1
+ if rows == number_of_rows:
+ break
return table
@@ -144,6 +215,7 @@ class Result(object):
def NeedsBaseline(self):
return False
+ # pylint: disable=unused-argument
def _Literal(self, cell, values, baseline_values):
cell.value = " ".join([str(v) for v in values])
@@ -178,7 +250,7 @@ class Result(object):
"""
all_floats = True
values = _StripNone(values)
- if not len(values):
+ if not values:
cell.value = ""
return
if _AllFloat(values):
@@ -211,16 +283,25 @@ class LiteralResult(Result):
def Compute(self, cell, values, baseline_values):
try:
- if values[self.iteration]:
- cell.value = values[self.iteration]
- else:
- cell.value = "-"
+ cell.value = values[self.iteration]
except IndexError:
cell.value = "-"
class NonEmptyCountResult(Result):
+ """A class that counts the number of non-empty results.
+
+ The number of non-empty values will be stored in the cell.
+ """
+
def Compute(self, cell, values, baseline_values):
+ """Put the number of non-empty values in the cell result.
+
+ Args:
+ cell: Put the result in cell.value.
+ values: A list of values for the row.
+ baseline_values: A list of baseline values for the row.
+ """
cell.value = len(_StripNone(values))
if not baseline_values:
return
@@ -231,8 +312,8 @@ class NonEmptyCountResult(Result):
len_values = len(values)
len_baseline_values = len(baseline_values)
tmp_cell = Cell()
- tmp_cell.value= 1.0 + (float(cell.value - base_value) /
- (max(len_values, len_baseline_values)))
+ tmp_cell.value = 1.0 + (float(cell.value - base_value) /
+ (max(len_values, len_baseline_values)))
f.Compute(tmp_cell)
cell.bgcolor = tmp_cell.bgcolor
@@ -244,6 +325,7 @@ class StringMeanResult(Result):
else:
cell.value = "?"
+
class AmeanResult(StringMeanResult):
def _ComputeFloat(self, cell, values, baseline_values):
cell.value = numpy.mean(values)
@@ -316,7 +398,7 @@ class PValueResult(ComparisonResult):
if len(values) < 2 or len(baseline_values) < 2:
cell.value = float("nan")
return
- import stats
+ import stats # pylint: disable=g-import-not-at-top
_, cell.value = stats.lttest_ind(values, baseline_values)
def _ComputeString(self, cell, values, baseline_values):
@@ -462,12 +544,11 @@ class PValueFormat(Format):
cell.string_value = "%0.2f" % float(cell.value)
if float(cell.value) < 0.05:
cell.bgcolor = self._GetColor(cell.value,
- Color(255, 255, 0, 0),
- Color(255, 255, 255, 0),
- Color(255, 255, 255, 0),
- mid_value=0.05,
- power=1)
- cell.bgcolor_row = True
+ Color(255, 255, 0, 0),
+ Color(255, 255, 255, 0),
+ Color(255, 255, 255, 0),
+ mid_value=0.05,
+ power=1)
class StorageFormat(Format):
@@ -802,6 +883,7 @@ class TablePrinter(object):
if self._output_type == self.CONSOLE:
rgb = color.GetRGB()
prefix, _ = colortrans.rgb2short(rgb)
+ # pylint: disable=anomalous-backslash-in-string
prefix = "\033[48;5;%sm" % prefix
suffix = "\033[0m"
elif self._output_type in [self.EMAIL, self.HTML]:
@@ -818,6 +900,7 @@ class TablePrinter(object):
if self._output_type == self.CONSOLE:
rgb = color.GetRGB()
prefix, _ = colortrans.rgb2short(rgb)
+ # pylint: disable=anomalous-backslash-in-string
prefix = "\033[38;5;%sm" % prefix
suffix = "\033[0m"
elif self._output_type in [self.EMAIL, self.HTML]:
@@ -965,7 +1048,21 @@ def GetSimpleTable(table, out_to=TablePrinter.CONSOLE):
return tp.Print()
+# pylint: disable=redefined-outer-name
def GetComplexTable(runs, labels, out_to=TablePrinter.CONSOLE):
+ """Prints a complex table.
+
+ This can be used to generate a table with arithmetic mean, standard deviation,
+ coefficient of variation, p-values, etc.
+
+ Args:
+ runs: A list of lists with data to tabulate.
+ labels: A list of labels that correspond to the runs.
+ out_to: specifies the format of the table (example CONSOLE or HTML).
+
+ Returns:
+ A string table that can be printed to the console or put in an HTML file.
+ """
tg = TableGenerator(runs, labels, TableGenerator.SORT_BY_VALUES_DESC)
table = tg.GetTable()
columns = [Column(LiteralResult(),
@@ -995,33 +1092,21 @@ def GetComplexTable(runs, labels, out_to=TablePrinter.CONSOLE):
if __name__ == "__main__":
# Run a few small tests here.
- runs = [
- [
- {"k1": "10", "k2": "12", "k5": "40", "k6": "40",
- "ms_1": "20", "k7": "FAIL", "k8": "PASS", "k9": "PASS",
- "k10": "0"},
- {"k1": "13", "k2": "14", "k3": "15", "ms_1": "10", "k8": "PASS",
- "k9": "FAIL", "k10": "0"}
- ],
- [
- {"k1": "50", "k2": "51", "k3": "52", "k4": "53", "k5": "35", "k6":
- "45", "ms_1": "200", "ms_2": "20", "k7": "FAIL", "k8": "PASS", "k9":
- "PASS"},
- ],
- ]
+ runs = [[{"k1": "10", "k2": "12", "k5": "40", "k6": "40",
+ "ms_1": "20", "k7": "FAIL", "k8": "PASS", "k9": "PASS",
+ "k10": "0"},
+ {"k1": "13", "k2": "14", "k3": "15", "ms_1": "10", "k8": "PASS",
+ "k9": "FAIL", "k10": "0"}],
+ [{"k1": "50", "k2": "51", "k3": "52", "k4": "53", "k5": "35", "k6":
+ "45", "ms_1": "200", "ms_2": "20", "k7": "FAIL", "k8": "PASS", "k9":
+ "PASS"}]]
labels = ["vanilla", "modified"]
t = GetComplexTable(runs, labels, TablePrinter.CONSOLE)
print t
email = GetComplexTable(runs, labels, TablePrinter.EMAIL)
- runs = [
- [
- {"k1": "1",}, {"k1": "1.1"}, {"k1": "1.2"},
- ],
- [
- {"k1": "5",}, {"k1": "5.1"}, {"k1": "5.2"},
- ],
- ]
+ runs = [[{"k1": "1"}, {"k1": "1.1"}, {"k1": "1.2"}],
+ [{"k1": "5"}, {"k1": "5.1"}, {"k1": "5.2"}]]
t = GetComplexTable(runs, labels, TablePrinter.CONSOLE)
print t
diff --git a/utils/tabulator_test.py b/utils/tabulator_test.py
index 54b455d3..16406107 100644
--- a/utils/tabulator_test.py
+++ b/utils/tabulator_test.py
@@ -1,6 +1,6 @@
# Copyright 2012 Google Inc. All Rights Reserved.
-"""Tests for misc."""
+"""Tests for the tabulator module."""
__author__ = "asharif@google.com (Ahmad Sharif)"
@@ -69,7 +69,7 @@ class TabulatorTest(unittest.TestCase):
def testTableGenerator(self):
runs = [[{"k1": "10", "k2": "12"},
{"k1": "13", "k2": "14", "k3": "15"}],
- [{"k1": "50", "k2": "51", "k3": "52", "k4": "53"},]]
+ [{"k1": "50", "k2": "51", "k3": "52", "k4": "53"}]]
labels = ["vanilla", "modified"]
tg = tabulator.TableGenerator(runs, labels)
table = tg.GetTable()
diff --git a/v14/README b/v14/README
deleted file mode 100644
index 3ab3d7b7..00000000
--- a/v14/README
+++ /dev/null
@@ -1,10 +0,0 @@
-To run scripts in this directory, first run:
-
-export PYTHONPATH=$(readlink -f .):$PYTHONPATH
-
-from this directory.
-
-Then you can run any script.
-
-To get help on any script, type in python <script> --help, or refer to the
-header of the script for more information.
diff --git a/v14/crosperf/autotest_runner.py b/v14/crosperf/autotest_runner.py
deleted file mode 100644
index 5611b655..00000000
--- a/v14/crosperf/autotest_runner.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-from utils import command_executer
-
-
-class AutotestRunner(object):
- """ This defines the interface from crosperf to ./run_remote_tests.sh.
- """
- def __init__(self, logger_to_use=None):
- self._logger = logger_to_use
- self._ce = command_executer.GetCommandExecuter(self._logger)
- self._ct = command_executer.CommandTerminator()
-
- def Run(self, machine_name, chromeos_root, board, autotest_name,
- autotest_args):
- """Run the run_remote_test."""
- options = ""
- if board:
- options += " --board=%s" % board
- if autotest_args:
- options += " %s" % autotest_args
- command = "rm -rf /usr/local/autotest/results/*"
- self._ce.CrosRunCommand(command, machine=machine_name, username="root",
- chromeos_root=chromeos_root)
- command = ("./run_remote_tests.sh --remote=%s %s %s" %
- (machine_name, options, autotest_name))
- return self._ce.ChrootRunCommand(chromeos_root, command, True, self._ct)
-
- def Terminate(self):
- self._ct.Terminate()
-
-
-class MockAutotestRunner(object):
- def __init__(self):
- pass
-
- def Run(self, *args):
- return ["", "", 0]
diff --git a/v14/crosperf/benchmark.py b/v14/crosperf/benchmark.py
deleted file mode 100644
index 8fe8a492..00000000
--- a/v14/crosperf/benchmark.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-
-class Benchmark(object):
- """Class representing a benchmark to be run.
-
- Contains details of the autotest, arguments to pass to the autotest,
- iterations to run the autotest and so on. Note that the benchmark name
- can be different to the autotest name. For example, you may want to have
- two different benchmarks which run the same autotest with different
- arguments.
- """
-
- def __init__(self, name, autotest_name, autotest_args, iterations,
- outlier_range, key_results_only, rm_chroot_tmp, perf_args):
- self.name = name
- self.autotest_name = autotest_name
- self.autotest_args = autotest_args
- self.iterations = iterations
- self.outlier_range = outlier_range
- self.perf_args = perf_args
- self.key_results_only = key_results_only
- self.rm_chroot_tmp = rm_chroot_tmp
- self.iteration_adjusted = False
diff --git a/v14/crosperf/benchmark_run.py b/v14/crosperf/benchmark_run.py
deleted file mode 100644
index 80c95c4d..00000000
--- a/v14/crosperf/benchmark_run.py
+++ /dev/null
@@ -1,198 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-import datetime
-import os
-import threading
-import time
-import traceback
-
-from utils import command_executer
-from utils import timeline
-
-from autotest_runner import AutotestRunner
-from results_cache import Result
-from results_cache import ResultsCache
-
-STATUS_FAILED = "FAILED"
-STATUS_SUCCEEDED = "SUCCEEDED"
-STATUS_IMAGING = "IMAGING"
-STATUS_RUNNING = "RUNNING"
-STATUS_WAITING = "WAITING"
-STATUS_PENDING = "PENDING"
-
-
-class BenchmarkRun(threading.Thread):
- def __init__(self, name, benchmark,
- label,
- iteration,
- cache_conditions,
- machine_manager,
- logger_to_use,
- share_users):
- threading.Thread.__init__(self)
- self.name = name
- self._logger = logger_to_use
- self.benchmark = benchmark
- self.iteration = iteration
- self.label = label
- self.result = None
- self.terminated = False
- self.retval = None
- self.run_completed = False
- self.machine_manager = machine_manager
- self.cache = ResultsCache()
- self.autotest_runner = AutotestRunner(self._logger)
- self.machine = None
- self.cache_conditions = cache_conditions
- self.runs_complete = 0
- self.cache_hit = False
- self.failure_reason = ""
- self.autotest_args = "%s %s" % (benchmark.autotest_args,
- self._GetExtraAutotestArgs())
- self._ce = command_executer.GetCommandExecuter(self._logger)
- self.timeline = timeline.Timeline()
- self.timeline.Record(STATUS_PENDING)
- self.share_users = share_users
-
- def run(self):
- try:
- # Just use the first machine for running the cached version,
- # without locking it.
- self.cache.Init(self.label.chromeos_image,
- self.label.chromeos_root,
- self.benchmark.autotest_name,
- self.iteration,
- self.autotest_args,
- self.machine_manager,
- self.label.board,
- self.cache_conditions,
- self._logger,
- self.label,
- self.share_users
- )
-
- self.result = self.cache.ReadResult()
- self.cache_hit = (self.result is not None)
-
- if self.result:
- self._logger.LogOutput("%s: Cache hit." % self.name)
- self._logger.LogOutput(self.result.out, print_to_console=False)
- self._logger.LogError(self.result.err, print_to_console=False)
-
- else:
- self._logger.LogOutput("%s: No cache hit." % self.name)
- self.timeline.Record(STATUS_WAITING)
- # Try to acquire a machine now.
- self.machine = self.AcquireMachine()
- self.cache.remote = self.machine.name
- self.result = self.RunTest(self.machine)
- self.cache.StoreResult(self.result)
-
- if self.terminated:
- return
-
- if not self.result.retval:
- self.timeline.Record(STATUS_SUCCEEDED)
- else:
- if self.timeline.GetLastEvent() != STATUS_FAILED:
- self.failure_reason = "Return value of autotest was non-zero."
- self.timeline.Record(STATUS_FAILED)
-
- except Exception, e:
- self._logger.LogError("Benchmark run: '%s' failed: %s" % (self.name, e))
- traceback.print_exc()
- if self.timeline.GetLastEvent() != STATUS_FAILED:
- self.timeline.Record(STATUS_FAILED)
- self.failure_reason = str(e)
- finally:
- if self.machine:
- self._logger.LogOutput("Releasing machine: %s" % self.machine.name)
- self.machine_manager.ReleaseMachine(self.machine)
- self._logger.LogOutput("Released machine: %s" % self.machine.name)
-
- def Terminate(self):
- self.terminated = True
- self.autotest_runner.Terminate()
- if self.timeline.GetLastEvent() != STATUS_FAILED:
- self.timeline.Record(STATUS_FAILED)
- self.failure_reason = "Thread terminated."
-
- def AcquireMachine(self):
- while True:
- if self.terminated:
- raise Exception("Thread terminated while trying to acquire machine.")
- machine = self.machine_manager.AcquireMachine(self.label.chromeos_image,
- self.label)
-
- if machine:
- self._logger.LogOutput("%s: Machine %s acquired at %s" %
- (self.name,
- machine.name,
- datetime.datetime.now()))
- break
- else:
- sleep_duration = 10
- time.sleep(sleep_duration)
- return machine
-
- def _GetExtraAutotestArgs(self):
- if self.benchmark.perf_args:
- perf_args_list = self.benchmark.perf_args.split(" ")
- perf_args_list = [perf_args_list[0]] + ["-a"] + perf_args_list[1:]
- perf_args = " ".join(perf_args_list)
- if not perf_args_list[0] in ["record", "stat"]:
- raise Exception("perf_args must start with either record or stat")
- extra_autotest_args = ["--profiler=custom_perf",
- ("--profiler_args='perf_options=\"%s\"'" %
- perf_args)]
- return " ".join(extra_autotest_args)
- else:
- return ""
-
- def RunTest(self, machine):
- self.timeline.Record(STATUS_IMAGING)
- self.machine_manager.ImageMachine(machine,
- self.label)
- self.timeline.Record(STATUS_RUNNING)
- [retval, out, err] = self.autotest_runner.Run(machine.name,
- self.label.chromeos_root,
- self.label.board,
- self.benchmark.autotest_name,
- self.autotest_args)
- self.run_completed = True
-
- return Result.CreateFromRun(self._logger,
- self.label.chromeos_root,
- self.label.board,
- self.label.name,
- out,
- err,
- retval)
-
- def SetCacheConditions(self, cache_conditions):
- self.cache_conditions = cache_conditions
-
-
-class MockBenchmarkRun(BenchmarkRun):
- """Inherited from BenchmarkRun, just overide RunTest for testing."""
-
- def RunTest(self, machine):
- """Remove Result.CreateFromRun for testing."""
- self.timeline.Record(STATUS_IMAGING)
- self.machine_manager.ImageMachine(machine,
- self.label)
- self.timeline.Record(STATUS_RUNNING)
- [retval, out, err] = self.autotest_runner.Run(machine.name,
- self.label.chromeos_root,
- self.label.board,
- self.benchmark.autotest_name,
- self.autotest_args)
- self.run_completed = True
- rr = Result("Results placed in /tmp/test", "", 0)
- rr.out = out
- rr.err = err
- rr.retval = retval
- return rr
-
diff --git a/v14/crosperf/benchmark_run_unittest.py b/v14/crosperf/benchmark_run_unittest.py
deleted file mode 100755
index 47e027f4..00000000
--- a/v14/crosperf/benchmark_run_unittest.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-"""Testing of benchmark_run."""
-
-import unittest
-
-from utils import logger
-
-from autotest_runner import MockAutotestRunner
-from benchmark_run import MockBenchmarkRun
-from label import MockLabel
-from benchmark import Benchmark
-from machine_manager import MockMachineManager
-from results_cache import MockResultsCache
-
-
-class BenchmarkRunTest(unittest.TestCase):
- def testDryRun(self):
- my_label = MockLabel("test1", "image1", "/tmp/test_benchmark_run",
- "x86-alex", "chromeos-alex1",
- image_args="",
- image_md5sum="",
- cache_dir="")
- m = MockMachineManager("/tmp/chromeos_root", 0)
- m.AddMachine("chromeos-alex1")
- bench = Benchmark("PageCyler",
- "Pyautoperf",
- "",
- 1,
- 0.2,
- False,
- False,
- "")
- b = MockBenchmarkRun("test run",
- bench,
- my_label,
- 1,
- [],
- m,
- logger.GetLogger(),
- "")
- b.cache = MockResultsCache()
- b.autotest_runner = MockAutotestRunner()
- b.start()
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/v14/crosperf/column_chart.py b/v14/crosperf/column_chart.py
deleted file mode 100644
index 22a45c5b..00000000
--- a/v14/crosperf/column_chart.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-
-class ColumnChart(object):
- def __init__(self, title, width, height):
- self.title = title
- self.chart_div = filter(str.isalnum, title)
- self.width = width
- self.height = height
- self.columns = []
- self.rows = []
- self.series = []
-
- def AddSeries(self, column_name, series_type, color):
- for i in range(len(self.columns)):
- if column_name == self.columns[i][1]:
- self.series.append((i - 1, series_type, color))
- break
-
- def AddColumn(self, name, column_type):
- self.columns.append((column_type, name))
-
- def AddRow(self, row):
- self.rows.append(row)
-
- def GetJavascript(self):
- res = "var data = new google.visualization.DataTable();\n"
- for column in self.columns:
- res += "data.addColumn('%s', '%s');\n" % column
- res += "data.addRows(%s);\n" % len(self.rows)
- for row in range(len(self.rows)):
- for column in range(len(self.columns)):
- val = self.rows[row][column]
- if isinstance(val, str):
- val = "'%s'" % val
- res += "data.setValue(%s, %s, %s);\n" % (row, column, val)
-
- series_javascript = ""
- for series in self.series:
- series_javascript += "%s: {type: '%s', color: '%s'}, " % series
-
- chart_add_javascript = """
-var chart_%s = new google.visualization.ComboChart(
- document.getElementById('%s'));
-chart_%s.draw(data, {width: %s, height: %s, title: '%s', legend: 'none',
- seriesType: "bars", lineWidth: 0, pointSize: 5, series: {%s},
- vAxis: {minValue: 0}})
-"""
- res += chart_add_javascript % (self.chart_div, self.chart_div,
- self.chart_div, self.width,
- self.height, self.title, series_javascript)
- return res
-
- def GetDiv(self):
- return "<div id='%s' class='chart'></div>" % self.chart_div
diff --git a/v14/crosperf/crosperf b/v14/crosperf/crosperf
deleted file mode 100755
index 904a172a..00000000
--- a/v14/crosperf/crosperf
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-PYTHONPATH=$(dirname $0)/..:$PYTHONPATH python $(dirname $0)/crosperf.py "$@"
diff --git a/v14/crosperf/crosperf.py b/v14/crosperf/crosperf.py
deleted file mode 100755
index cb7911fd..00000000
--- a/v14/crosperf/crosperf.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-"""The driver script for running performance benchmarks on ChromeOS."""
-
-import atexit
-import optparse
-import os
-import sys
-from experiment_runner import ExperimentRunner
-from experiment_runner import MockExperimentRunner
-from experiment_factory import ExperimentFactory
-from experiment_file import ExperimentFile
-from help import Help
-from settings_factory import GlobalSettings
-from utils import logger
-
-import test_flag
-
-
-class MyIndentedHelpFormatter(optparse.IndentedHelpFormatter):
- def format_description(self, description):
- return description
-
-
-def SetupParserOptions(parser):
- """Add all options to the parser."""
- parser.add_option("--dry_run",
- dest="dry_run",
- help=("Parse the experiment file and "
- "show what will be done"),
- action="store_true",
- default=False)
- # Allow each of the global fields to be overridden by passing in
- # options. Add each global field as an option.
- option_settings = GlobalSettings("")
- for field_name in option_settings.fields:
- field = option_settings.fields[field_name]
- parser.add_option("--%s" % field.name,
- dest=field.name,
- help=field.description,
- action="store")
-
-
-def ConvertOptionsToSettings(options):
- """Convert options passed in into global settings."""
- option_settings = GlobalSettings("option_settings")
- for option_name in options.__dict__:
- if (options.__dict__[option_name] is not None and
- option_name in option_settings.fields):
- option_settings.SetField(option_name, options.__dict__[option_name])
- return option_settings
-
-
-def Cleanup(experiment):
- """Handler function which is registered to the atexit handler."""
- experiment.Cleanup()
-
-
-def Main(argv):
- parser = optparse.OptionParser(usage=Help().GetUsage(),
- description=Help().GetHelp(),
- formatter=MyIndentedHelpFormatter(),
- version="%prog 0.1")
-
- parser.add_option("-l", "--log_dir",
- dest="log_dir",
- default="",
- help="The log_dir, default is under <crosperf_logs>/logs")
-
- SetupParserOptions(parser)
- options, args = parser.parse_args(argv)
-
- # Convert the relevant options that are passed in into a settings
- # object which will override settings in the experiment file.
- option_settings = ConvertOptionsToSettings(options)
- log_dir = os.path.abspath(os.path.expanduser(options.log_dir))
- logger.GetLogger(log_dir)
-
- if len(args) == 2:
- experiment_filename = args[1]
- else:
- parser.error("Invalid number arguments.")
-
- working_directory = os.getcwd()
- if options.dry_run:
- test_flag.SetTestMode(True)
-
- experiment_file = ExperimentFile(open(experiment_filename, "rb"),
- option_settings)
- if not experiment_file.GetGlobalSettings().GetField("name"):
- experiment_name = os.path.basename(experiment_filename)
- experiment_file.GetGlobalSettings().SetField("name", experiment_name)
- experiment = ExperimentFactory().GetExperiment(experiment_file,
- working_directory,
- log_dir)
-
- atexit.register(Cleanup, experiment)
-
- if options.dry_run:
- runner = MockExperimentRunner(experiment)
- else:
- runner = ExperimentRunner(experiment)
- runner.Run()
-
-if __name__ == "__main__":
- Main(sys.argv)
diff --git a/v14/crosperf/crosperf_test.py b/v14/crosperf/crosperf_test.py
deleted file mode 100755
index 0c50e7b5..00000000
--- a/v14/crosperf/crosperf_test.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-import os
-import tempfile
-import unittest
-import crosperf
-from utils.file_utils import FileUtils
-
-
-EXPERIMENT_FILE_1 = """
- board: x86-alex
- remote: chromeos-alex3
-
- benchmark: PageCycler {
- iterations: 3
- }
-
- image1 {
- chromeos_image: /usr/local/google/cros_image1.bin
- }
-
- image2 {
- chromeos_image: /usr/local/google/cros_image2.bin
- }
- """
-
-
-class CrosPerfTest(unittest.TestCase):
- def testDryRun(self):
- filehandle, filename = tempfile.mkstemp()
- os.write(filehandle, EXPERIMENT_FILE_1)
- crosperf.Main(["", filename, "--dry_run"])
- os.remove(filename)
-
-
-if __name__ == "__main__":
- FileUtils.Configure(True)
- unittest.main()
diff --git a/v14/crosperf/default_remotes b/v14/crosperf/default_remotes
deleted file mode 100644
index 5efaebcd..00000000
--- a/v14/crosperf/default_remotes
+++ /dev/null
@@ -1,5 +0,0 @@
-x86-zgb : chromeos1-rack3-host4.cros chromeos1-rack3-host5.cros chromeos1-rack3-host6.cros
-x86-alex : chromeos2-row1-rack4-host7.cros chromeos2-row1-rack4-host8.cros chromeos2-row1-rack4-host9.cros
-lumpy : chromeos2-row2-rack4-host10.cros chromeos2-row2-rack4-host11.cros chromeos2-row2-rack4-host12.cros
-stumpy : chromeos2-row3-rack7-host1.cros chromeos2-row3-rack7-host2.cros chromeos2-row3-rack7-host3.cros
-
diff --git a/v14/crosperf/experiment.py b/v14/crosperf/experiment.py
deleted file mode 100644
index 2a4590c4..00000000
--- a/v14/crosperf/experiment.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-"""The experiment setting module."""
-
-import os
-import time
-
-from utils import logger
-
-from benchmark_run import BenchmarkRun
-from machine_manager import MachineManager
-from machine_manager import MockMachineManager
-import test_flag
-
-
-class Experiment(object):
- """Class representing an Experiment to be run."""
-
- def __init__(self, name, remote, working_directory,
- chromeos_root, cache_conditions, labels, benchmarks,
- experiment_file, email_to, acquire_timeout, log_dir,
- share_users):
- self.name = name
- self.working_directory = working_directory
- self.remote = remote
- self.chromeos_root = chromeos_root
- self.cache_conditions = cache_conditions
- self.experiment_file = experiment_file
- self.email_to = email_to
- self.results_directory = os.path.join(self.working_directory,
- self.name + "_results")
- self.log_dir = log_dir
- self.labels = labels
- self.benchmarks = benchmarks
- self.num_complete = 0
- self.num_run_complete = 0
- self.share_users = share_users
-
- # We need one chromeos_root to run the benchmarks in, but it doesn't
- # matter where it is, unless the ABIs are different.
- if not chromeos_root:
- for label in self.labels:
- if label.chromeos_root:
- chromeos_root = label.chromeos_root
- if not chromeos_root:
- raise Exception("No chromeos_root given and could not determine one from "
- "the image path.")
-
- if test_flag.GetTestMode():
- self.machine_manager = MockMachineManager(chromeos_root, acquire_timeout)
- else:
- self.machine_manager = MachineManager(chromeos_root, acquire_timeout)
- self.l = logger.GetLogger(log_dir)
-
- for machine in remote:
- self.machine_manager.AddMachine(machine)
- for label in labels:
- self.machine_manager.ComputeCommonCheckSum(label)
- self.machine_manager.ComputeCommonCheckSumString(label)
-
- self.start_time = None
- self.benchmark_runs = self._GenerateBenchmarkRuns()
-
- def _GenerateBenchmarkRuns(self):
- """Generate benchmark runs from labels and benchmark defintions."""
- benchmark_runs = []
- for label in self.labels:
- for benchmark in self.benchmarks:
- for iteration in range(1, benchmark.iterations + 1):
-
- benchmark_run_name = "%s: %s (%s)" % (label.name, benchmark.name,
- iteration)
- full_name = "%s_%s_%s" % (label.name, benchmark.name, iteration)
- logger_to_use = logger.Logger(self.log_dir,
- "run.%s" % (full_name),
- True)
- benchmark_run = BenchmarkRun(benchmark_run_name,
- benchmark,
- label,
- iteration,
- self.cache_conditions,
- self.machine_manager,
- logger_to_use,
- self.share_users)
-
- benchmark_runs.append(benchmark_run)
- return benchmark_runs
-
- def Build(self):
- pass
-
- def Terminate(self):
- for t in self.benchmark_runs:
- if t.isAlive():
- self.l.LogError("Terminating run: '%s'." % t.name)
- t.Terminate()
-
- def IsComplete(self):
- if self.active_threads:
- for t in self.active_threads:
- if t.isAlive():
- t.join(0)
- if not t.isAlive():
- self.num_complete += 1
- if not t.cache_hit:
- self.num_run_complete += 1
- self.active_threads.remove(t)
- return False
- return True
-
- def Run(self):
- self.start_time = time.time()
- self.active_threads = []
- for benchmark_run in self.benchmark_runs:
- # Set threads to daemon so program exits when ctrl-c is pressed.
- benchmark_run.daemon = True
- benchmark_run.start()
- self.active_threads.append(benchmark_run)
-
- def SetCacheConditions(self, cache_conditions):
- for benchmark_run in self.benchmark_runs:
- benchmark_run.SetCacheConditions(cache_conditions)
-
- def Cleanup(self):
- self.machine_manager.Cleanup()
diff --git a/v14/crosperf/experiment_factory.py b/v14/crosperf/experiment_factory.py
deleted file mode 100644
index 3c92ee3e..00000000
--- a/v14/crosperf/experiment_factory.py
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-"""A module to generate experments."""
-
-import os
-import socket
-
-from benchmark import Benchmark
-import config
-from experiment import Experiment
-from label import Label
-from label import MockLabel
-from results_cache import CacheConditions
-import test_flag
-
-
-class ExperimentFactory(object):
- """Factory class for building an Experiment, given an ExperimentFile as input.
-
- This factory is currently hardcoded to produce an experiment for running
- ChromeOS benchmarks, but the idea is that in the future, other types
- of experiments could be produced.
- """
-
- def GetExperiment(self, experiment_file, working_directory, log_dir):
- """Construct an experiment from an experiment file."""
- global_settings = experiment_file.GetGlobalSettings()
- experiment_name = global_settings.GetField("name")
- remote = global_settings.GetField("remote")
- chromeos_root = global_settings.GetField("chromeos_root")
- rm_chroot_tmp = global_settings.GetField("rm_chroot_tmp")
- key_results_only = global_settings.GetField("key_results_only")
- acquire_timeout= global_settings.GetField("acquire_timeout")
- cache_dir = global_settings.GetField("cache_dir")
- config.AddConfig("no_email", global_settings.GetField("no_email"))
- share_users = global_settings.GetField("share_users")
-
- # Default cache hit conditions. The image checksum in the cache and the
- # computed checksum of the image must match. Also a cache file must exist.
- cache_conditions = [CacheConditions.CACHE_FILE_EXISTS,
- CacheConditions.CHECKSUMS_MATCH]
- if global_settings.GetField("rerun_if_failed"):
- cache_conditions.append(CacheConditions.RUN_SUCCEEDED)
- if global_settings.GetField("rerun"):
- cache_conditions.append(CacheConditions.FALSE)
- if global_settings.GetField("same_machine"):
- cache_conditions.append(CacheConditions.SAME_MACHINE_MATCH)
- if global_settings.GetField("same_specs"):
- cache_conditions.append(CacheConditions.MACHINES_MATCH)
-
- # Construct benchmarks.
- benchmarks = []
- all_benchmark_settings = experiment_file.GetSettings("benchmark")
- for benchmark_settings in all_benchmark_settings:
- benchmark_name = benchmark_settings.name
- autotest_name = benchmark_settings.GetField("autotest_name")
- if not autotest_name:
- autotest_name = benchmark_name
- autotest_args = benchmark_settings.GetField("autotest_args")
- iterations = benchmark_settings.GetField("iterations")
- outlier_range = benchmark_settings.GetField("outlier_range")
- perf_args = benchmark_settings.GetField("perf_args")
- rm_chroot_tmp = benchmark_settings.GetField("rm_chroot_tmp")
- key_results_only = benchmark_settings.GetField("key_results_only")
-
- benchmark = Benchmark(benchmark_name, autotest_name, autotest_args,
- iterations, outlier_range,
- key_results_only, rm_chroot_tmp,
- perf_args)
- benchmarks.append(benchmark)
-
- # Construct labels.
- labels = []
- all_label_settings = experiment_file.GetSettings("label")
- all_remote = list(remote)
- for label_settings in all_label_settings:
- label_name = label_settings.name
- image = label_settings.GetField("chromeos_image")
- chromeos_root = label_settings.GetField("chromeos_root")
- board = label_settings.GetField("board")
- my_remote = label_settings.GetField("remote")
- image_md5sum = label_settings.GetField("md5sum")
- cache_dir = label_settings.GetField("cache_dir")
- # TODO(yunlian): We should consolidate code in machine_manager.py
- # to derermine whether we are running from within google or not
- if ("corp.google.com" in socket.gethostname() and
- (not my_remote
- or my_remote == remote
- and global_settings.GetField("board") != board)):
- my_remote = self.GetDefaultRemotes(board)
- if global_settings.GetField("same_machine") and len(my_remote) > 1:
- raise Exception("Only one remote is allowed when same_machine "
- "is turned on")
- all_remote += my_remote
- image_args = label_settings.GetField("image_args")
- if test_flag.GetTestMode():
- label = MockLabel(label_name, image, chromeos_root, board, my_remote,
- image_args, image_md5sum, cache_dir)
- else:
- label = Label(label_name, image, chromeos_root, board, my_remote,
- image_args, image_md5sum, cache_dir)
- labels.append(label)
-
- email = global_settings.GetField("email")
- all_remote = list(set(all_remote))
- experiment = Experiment(experiment_name, all_remote,
- working_directory, chromeos_root,
- cache_conditions, labels, benchmarks,
- experiment_file.Canonicalize(),
- email, acquire_timeout, log_dir, share_users)
-
- return experiment
-
- def GetDefaultRemotes(self, board):
- default_remotes_file = os.path.join(os.path.dirname(__file__),
- "default_remotes")
- try:
- with open(default_remotes_file) as f:
- for line in f:
- key, v = line.split(":")
- if key.strip() == board:
- remotes = v.strip().split(" ")
- if remotes:
- return remotes
- else:
- raise Exception("There is not remote for {0}".format(board))
- except IOError:
- raise Exception("IOError while reading file {0}"
- .format(default_remotes_file))
- else:
- raise Exception("There is not remote for {0}".format(board))
-
-
-
diff --git a/v14/crosperf/experiment_factory_unittest.py b/v14/crosperf/experiment_factory_unittest.py
deleted file mode 100755
index 6cee6b74..00000000
--- a/v14/crosperf/experiment_factory_unittest.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-import StringIO
-import unittest
-
-from utils.file_utils import FileUtils
-
-from experiment_factory import ExperimentFactory
-from experiment_file import ExperimentFile
-import test_flag
-
-EXPERIMENT_FILE_1 = """
- board: x86-alex
- remote: chromeos-alex3
-
- benchmark: PageCycler {
- iterations: 3
- }
-
- image1 {
- chromeos_image: /usr/local/google/cros_image1.bin
- }
-
- image2 {
- chromeos_image: /usr/local/google/cros_image2.bin
- }
- """
-
-
-class ExperimentFactoryTest(unittest.TestCase):
- def testLoadExperimentFile1(self):
- experiment_file = ExperimentFile(StringIO.StringIO(EXPERIMENT_FILE_1))
- experiment = ExperimentFactory().GetExperiment(experiment_file,
- working_directory="",
- log_dir="")
- self.assertEqual(experiment.remote, ["chromeos-alex3"])
-
- self.assertEqual(len(experiment.benchmarks), 1)
- self.assertEqual(experiment.benchmarks[0].name, "PageCycler")
- self.assertEqual(experiment.benchmarks[0].autotest_name, "PageCycler")
- self.assertEqual(experiment.benchmarks[0].iterations, 3)
-
- self.assertEqual(len(experiment.labels), 2)
- self.assertEqual(experiment.labels[0].chromeos_image,
- "/usr/local/google/cros_image1.bin")
- self.assertEqual(experiment.labels[0].board,
- "x86-alex")
-
-
-if __name__ == "__main__":
- FileUtils.Configure(True)
- test_flag.SetTestMode(True)
- unittest.main()
diff --git a/v14/crosperf/experiment_file.py b/v14/crosperf/experiment_file.py
deleted file mode 100644
index fc0f16ab..00000000
--- a/v14/crosperf/experiment_file.py
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import os.path
-import re
-from settings import Settings
-from settings_factory import SettingsFactory
-
-
-class ExperimentFile(object):
- """Class for parsing the experiment file format.
-
- The grammar for this format is:
-
- experiment = { _FIELD_VALUE_RE | settings }
- settings = _OPEN_SETTINGS_RE
- { _FIELD_VALUE_RE }
- _CLOSE_SETTINGS_RE
-
- Where the regexes are terminals defined below. This results in an format
- which looks something like:
-
- field_name: value
- settings_type: settings_name {
- field_name: value
- field_name: value
- }
- """
-
- # Field regex, e.g. "iterations: 3"
- _FIELD_VALUE_RE = re.compile("(\+)?\s*(\w+?)(?:\.(\S+))?\s*:\s*(.*)")
- # Open settings regex, e.g. "label {"
- _OPEN_SETTINGS_RE = re.compile("(?:(\w+):)?\s*(\w+)\s*{")
- # Close settings regex.
- _CLOSE_SETTINGS_RE = re.compile("}")
-
- def __init__(self, experiment_file, overrides=None):
- """Construct object from file-like experiment_file.
-
- Args:
- experiment_file: file-like object with text description of experiment.
- overrides: A settings object that will override fields in other settings.
-
- Raises:
- Exception: if invalid build type or description is invalid.
- """
- self.all_settings = []
- self.global_settings = SettingsFactory().GetSettings("global", "global")
- self.all_settings.append(self.global_settings)
-
- self._Parse(experiment_file)
-
- for settings in self.all_settings:
- settings.Inherit()
- settings.Validate()
- if overrides:
- settings.Override(overrides)
-
- def GetSettings(self, settings_type):
- """Return nested fields from the experiment file."""
- res = []
- for settings in self.all_settings:
- if settings.settings_type == settings_type:
- res.append(settings)
- return res
-
- def GetGlobalSettings(self):
- """Return the global fields from the experiment file."""
- return self.global_settings
-
- def _ParseField(self, reader):
- """Parse a key/value field."""
- line = reader.CurrentLine().strip()
- match = ExperimentFile._FIELD_VALUE_RE.match(line)
- append, name, _, text_value = match.groups()
- return (name, text_value, append)
-
- def _ParseSettings(self, reader):
- """Parse a settings block."""
- line = reader.CurrentLine().strip()
- match = ExperimentFile._OPEN_SETTINGS_RE.match(line)
- settings_type = match.group(1)
- if settings_type is None:
- settings_type = ""
- settings_name = match.group(2)
- settings = SettingsFactory().GetSettings(settings_name, settings_type)
- settings.SetParentSettings(self.global_settings)
-
- while reader.NextLine():
- line = reader.CurrentLine().strip()
-
- if not line:
- continue
- elif ExperimentFile._FIELD_VALUE_RE.match(line):
- field = self._ParseField(reader)
- settings.SetField(field[0], field[1], field[2])
- elif ExperimentFile._CLOSE_SETTINGS_RE.match(line):
- return settings
-
- raise Exception("Unexpected EOF while parsing settings block.")
-
- def _Parse(self, experiment_file):
- """Parse experiment file and create settings."""
- reader = ExperimentFileReader(experiment_file)
- settings_names = {}
- try:
- while reader.NextLine():
- line = reader.CurrentLine().strip()
-
- if not line:
- continue
- elif ExperimentFile._OPEN_SETTINGS_RE.match(line):
- new_settings = self._ParseSettings(reader)
- if new_settings.name in settings_names:
- raise Exception("Duplicate settings name: '%s'." %
- new_settings.name)
- settings_names[new_settings.name] = True
- self.all_settings.append(new_settings)
- elif ExperimentFile._FIELD_VALUE_RE.match(line):
- field = self._ParseField(reader)
- self.global_settings.SetField(field[0], field[1], field[2])
- else:
- raise Exception("Unexpected line.")
- except Exception, err:
- raise Exception("Line %d: %s\n==> %s" % (reader.LineNo(), str(err),
- reader.CurrentLine(False)))
-
- def Canonicalize(self):
- """Convert parsed experiment file back into an experiment file."""
- res = ""
- for field_name in self.global_settings.fields:
- field = self.global_settings.fields[field_name]
- if field.assigned:
- res += "%s: %s\n" % (field.name, field.GetString())
- res += "\n"
-
- for settings in self.all_settings:
- if settings.settings_type != "global":
- res += "%s: %s {\n" % (settings.settings_type, settings.name)
- for field_name in settings.fields:
- field = settings.fields[field_name]
- if field.assigned:
- res += "\t%s: %s\n" % (field.name, field.GetString())
- if field.name == "chromeos_image":
- real_file = (os.path.realpath
- (os.path.expanduser(field.GetString())))
- if real_file != field.GetString():
- res += "\t#actual_image: %s\n" % real_file
- res += "}\n\n"
-
- return res
-
-
-class ExperimentFileReader(object):
- """Handle reading lines from an experiment file."""
-
- def __init__(self, file_object):
- self.file_object = file_object
- self.current_line = None
- self.current_line_no = 0
-
- def CurrentLine(self, strip_comment=True):
- """Return the next line from the file, without advancing the iterator."""
- if strip_comment:
- return self._StripComment(self.current_line)
- return self.current_line
-
- def NextLine(self, strip_comment=True):
- """Advance the iterator and return the next line of the file."""
- self.current_line_no += 1
- self.current_line = self.file_object.readline()
- return self.CurrentLine(strip_comment)
-
- def _StripComment(self, line):
- """Strip comments starting with # from a line."""
- if "#" in line:
- line = line[:line.find("#")] + line[-1]
- return line
-
- def LineNo(self):
- """Return the current line number."""
- return self.current_line_no
diff --git a/v14/crosperf/experiment_file_unittest.py b/v14/crosperf/experiment_file_unittest.py
deleted file mode 100755
index d08c7eb5..00000000
--- a/v14/crosperf/experiment_file_unittest.py
+++ /dev/null
@@ -1,110 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import StringIO
-import unittest
-from experiment_file import ExperimentFile
-
-EXPERIMENT_FILE_1 = """
- board: x86-alex
- remote: chromeos-alex3
- perf_args: record -a -e cycles
- benchmark: PageCycler {
- iterations: 3
- }
-
- image1 {
- chromeos_image: /usr/local/google/cros_image1.bin
- }
-
- image2 {
- board: lumpy
- remote: chromeos-lumpy1
- chromeos_image: /usr/local/google/cros_image2.bin
- }
- """
-
-EXPERIMENT_FILE_2 = """
- board: x86-alex
- remote: chromeos-alex3
- iterations: 3
-
- benchmark: PageCycler {
- }
-
- benchmark: AndroidBench {
- iterations: 2
- }
-
- image1 {
- chromeos_image:/usr/local/google/cros_image1.bin
- }
-
- image2 {
- chromeos_image: /usr/local/google/cros_image2.bin
- }
- """
-
-EXPERIMENT_FILE_3 = """
- board: x86-alex
- remote: chromeos-alex3
- iterations: 3
-
- benchmark: PageCycler {
- }
-
- image1 {
- chromeos_image:/usr/local/google/cros_image1.bin
- }
-
- image1 {
- chromeos_image: /usr/local/google/cros_image2.bin
- }
- """
-
-
-class ExperimentFileTest(unittest.TestCase):
- def testLoadExperimentFile1(self):
- input_file = StringIO.StringIO(EXPERIMENT_FILE_1)
- experiment_file = ExperimentFile(input_file)
- global_settings = experiment_file.GetGlobalSettings()
- self.assertEqual(global_settings.GetField("remote"), ["chromeos-alex3"])
- self.assertEqual(global_settings.GetField("perf_args"),
- "record -a -e cycles")
- benchmark_settings = experiment_file.GetSettings("benchmark")
- self.assertEqual(len(benchmark_settings), 1)
- self.assertEqual(benchmark_settings[0].name, "PageCycler")
- self.assertEqual(benchmark_settings[0].GetField("iterations"), 3)
-
- label_settings = experiment_file.GetSettings("label")
- self.assertEqual(len(label_settings), 2)
- self.assertEqual(label_settings[0].name, "image1")
- self.assertEqual(label_settings[0].GetField("board"), "x86-alex")
- self.assertEqual(label_settings[0].GetField("chromeos_image"),
- "/usr/local/google/cros_image1.bin")
- self.assertEqual(label_settings[1].GetField("remote"), ["chromeos-lumpy1"])
- self.assertEqual(label_settings[0].GetField("remote"), ["chromeos-alex3"])
-
- def testOverrideSetting(self):
- input_file = StringIO.StringIO(EXPERIMENT_FILE_2)
- experiment_file = ExperimentFile(input_file)
- global_settings = experiment_file.GetGlobalSettings()
- self.assertEqual(global_settings.GetField("remote"), ["chromeos-alex3"])
-
- benchmark_settings = experiment_file.GetSettings("benchmark")
- self.assertEqual(len(benchmark_settings), 2)
- self.assertEqual(benchmark_settings[0].name, "PageCycler")
- self.assertEqual(benchmark_settings[0].GetField("iterations"), 3)
- self.assertEqual(benchmark_settings[1].name, "AndroidBench")
- self.assertEqual(benchmark_settings[1].GetField("iterations"), 2)
-
- def testDuplicateLabel(self):
- input_file = StringIO.StringIO(EXPERIMENT_FILE_3)
- self.assertRaises(Exception, ExperimentFile, input_file)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/v14/crosperf/experiment_files/README b/v14/crosperf/experiment_files/README
deleted file mode 100644
index 5c0e3d41..00000000
--- a/v14/crosperf/experiment_files/README
+++ /dev/null
@@ -1,26 +0,0 @@
-To use these experiment files, add board, remote and images and run crosperf
-on them.
-
-Further information about crosperf:
-https://sites.google.com/a/google.com/compiler-chromeos-workflows/crosperf
-
-The final experiment file should look something like the following:
-
-board: <board>
-remote: <ip address or machine name>
-
-# Add images you want to test:
-label: myimage {
- chromeos_image: <path to image>
-}
-
-# Paste experiment benchmarks here. Example, I pasted aes_perf here.
-
-# This experiment just runs a short autotest which measures the performance of
-# aes encryption. In addition, it profiles
-
-profile_type: record
-profile_counters: instructions cycles
-
-benchmark: platform_AesThroughput {
-}
diff --git a/v14/crosperf/experiment_files/aes_perf b/v14/crosperf/experiment_files/aes_perf
deleted file mode 100644
index 0c54ccbd..00000000
--- a/v14/crosperf/experiment_files/aes_perf
+++ /dev/null
@@ -1,7 +0,0 @@
-# This experiment just runs a short autotest which measures the performance of
-# aes encryption. In addition, it profiles
-
-profile_args: record -e cycles -e instructions
-
-benchmark: platform_AesThroughput {
-}
diff --git a/v14/crosperf/experiment_files/bloat_perf b/v14/crosperf/experiment_files/bloat_perf
deleted file mode 100644
index f8258ee1..00000000
--- a/v14/crosperf/experiment_files/bloat_perf
+++ /dev/null
@@ -1,6 +0,0 @@
-perf_args: record -e cycles
-
-benchmark: bloat {
- autotest_name: desktopui_PyAutoPerfTests
- autotest_args: --args='--iterations=1 perf.PageCyclerTest.testBloatFile'
-}
diff --git a/v14/crosperf/experiment_files/morejs_perf b/v14/crosperf/experiment_files/morejs_perf
deleted file mode 100644
index a02f15f5..00000000
--- a/v14/crosperf/experiment_files/morejs_perf
+++ /dev/null
@@ -1,6 +0,0 @@
-perf_args: record -e cycles
-
-benchmark: morejs {
- autotest_name: desktopui_PyAutoPerfTests
- autotest_args: --args='--iterations=1 perf.PageCyclerTest.testMoreJSFile'
-}
diff --git a/v14/crosperf/experiment_files/page_cycler b/v14/crosperf/experiment_files/page_cycler
deleted file mode 100644
index ada9ed67..00000000
--- a/v14/crosperf/experiment_files/page_cycler
+++ /dev/null
@@ -1,6 +0,0 @@
-# This experiment runs page cycler tests.
-
-benchmark: AllPageCyclers {
- autotest_name: desktopui_PyAutoPerfTests
- autotest_args: --args='perf.PageCyclerTest'
-}
diff --git a/v14/crosperf/experiment_files/page_cycler_perf b/v14/crosperf/experiment_files/page_cycler_perf
deleted file mode 100644
index 7f5e7118..00000000
--- a/v14/crosperf/experiment_files/page_cycler_perf
+++ /dev/null
@@ -1,43 +0,0 @@
-# This experiment profiles all page cyclers.
-
-perf_args: record -e cycles
-
-benchmark: morejs {
- autotest_name: desktopui_PyAutoPerfTests
- autotest_args: --args='--iterations=10 perf.PageCyclerTest.testMoreJSFile'
-}
-
-benchmark: alexa {
- autotest_name: desktopui_PyAutoPerfTests
- autotest_args: --args='--iterations=10 perf.PageCyclerTest.testAlexaFile'
-}
-
-benchmark: bloat {
- autotest_name: desktopui_PyAutoPerfTests
- autotest_args: --args='--iterations=10 perf.PageCyclerTest.testBloatFile'
-}
-
-benchmark: dhtml {
- autotest_name: desktopui_PyAutoPerfTests
- autotest_args: --args='--iterations=10 perf.PageCyclerTest.testDHTMLFile'
-}
-
-benchmark: intl1 {
- autotest_name: desktopui_PyAutoPerfTests
- autotest_args: --args='--iterations=10 perf.PageCyclerTest.testIntl1File'
-}
-
-benchmark: intl2 {
- autotest_name: desktopui_PyAutoPerfTests
- autotest_args: --args='--iterations=10 perf.PageCyclerTest.testIntl2File'
-}
-
-benchmark: moz {
- autotest_name: desktopui_PyAutoPerfTests
- autotest_args: --args='--iterations=10 perf.PageCyclerTest.testMozFile'
-}
-
-benchmark: moz2 {
- autotest_name: desktopui_PyAutoPerfTests
- autotest_args: --args='--iterations=10 perf.PageCyclerTest.testMoz2File'
-}
diff --git a/v14/crosperf/experiment_files/toolchain b/v14/crosperf/experiment_files/toolchain
deleted file mode 100644
index 9156998b..00000000
--- a/v14/crosperf/experiment_files/toolchain
+++ /dev/null
@@ -1,16 +0,0 @@
-# Use this experiment whenever the toolchain is upgraded.
-
-benchmark: bvt {
- autotest_name: suite:bvt
-}
-
-benchmark: suite_Smoke {
- autotest_name: suite:smoke
-}
-
-benchmark: PyAutoPerfTests {
-}
-
-benchmark: BootPerfServer {
- autotest_name: ^server/site_tests/platform_BootPerfServer/control$
-}
diff --git a/v14/crosperf/experiment_runner.py b/v14/crosperf/experiment_runner.py
deleted file mode 100644
index 9212ba56..00000000
--- a/v14/crosperf/experiment_runner.py
+++ /dev/null
@@ -1,132 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-"""The experiment runner module."""
-import getpass
-import os
-import time
-
-from utils import command_executer
-from utils import logger
-from utils.email_sender import EmailSender
-from utils.file_utils import FileUtils
-
-import config
-from experiment_status import ExperimentStatus
-from results_report import HTMLResultsReport
-from results_report import TextResultsReport
-
-
-class ExperimentRunner(object):
- """ExperimentRunner Class."""
-
- STATUS_TIME_DELAY = 30
- THREAD_MONITOR_DELAY = 2
-
- def __init__(self, experiment):
- self._experiment = experiment
- self.l = logger.GetLogger(experiment.log_dir)
- self._ce = command_executer.GetCommandExecuter(self.l)
- self._terminated = False
-
- def _Run(self, experiment):
- status = ExperimentStatus(experiment)
- experiment.Run()
- last_status_time = 0
- try:
- while not experiment.IsComplete():
- if last_status_time + self.STATUS_TIME_DELAY < time.time():
- last_status_time = time.time()
- border = "=============================="
- self.l.LogOutput(border)
- self.l.LogOutput(status.GetProgressString())
- self.l.LogOutput(status.GetStatusString())
- logger.GetLogger().LogOutput(border)
- time.sleep(self.THREAD_MONITOR_DELAY)
- except KeyboardInterrupt:
- self._terminated = True
- self.l.LogError("Ctrl-c pressed. Cleaning up...")
- experiment.Terminate()
-
- def _PrintTable(self, experiment):
- self.l.LogOutput(TextResultsReport(experiment).GetReport())
-
- def _Email(self, experiment):
- # Only email by default if a new run was completed.
- send_mail = False
- for benchmark_run in experiment.benchmark_runs:
- if not benchmark_run.cache_hit:
- send_mail = True
- break
- if (not send_mail and not experiment.email_to
- or config.GetConfig("no_email")):
- return
-
- label_names = []
- for label in experiment.labels:
- label_names.append(label.name)
- subject = "%s: %s" % (experiment.name, " vs. ".join(label_names))
-
- text_report = TextResultsReport(experiment, True).GetReport()
- text_report = "<pre style='font-size: 13px'>%s</pre>" % text_report
- html_report = HTMLResultsReport(experiment).GetReport()
- attachment = EmailSender.Attachment("report.html", html_report)
- email_to = [getpass.getuser()] + experiment.email_to
- EmailSender().SendEmail(email_to,
- subject,
- text_report,
- attachments=[attachment],
- msg_type="html")
-
- def _StoreResults (self, experiment):
- if self._terminated:
- return
- results_directory = experiment.results_directory
- FileUtils().RmDir(results_directory)
- FileUtils().MkDirP(results_directory)
- self.l.LogOutput("Storing experiment file.")
- experiment_file_path = os.path.join(results_directory,
- "experiment.exp")
- FileUtils().WriteFile(experiment_file_path, experiment.experiment_file)
-
- self.l.LogOutput("Storing results report.")
- results_table_path = os.path.join(results_directory, "results.html")
- report = HTMLResultsReport(experiment).GetReport()
- FileUtils().WriteFile(results_table_path, report)
-
- self.l.LogOutput("Storing results of each benchmark run.")
- for benchmark_run in experiment.benchmark_runs:
- if benchmark_run.result:
- benchmark_run_name = filter(str.isalnum, benchmark_run.name)
- benchmark_run_path = os.path.join(results_directory,
- benchmark_run_name)
- benchmark_run.result.CopyResultsTo(benchmark_run_path)
- benchmark_run.result.CleanUp(benchmark_run.benchmark.rm_chroot_tmp)
-
- def Run(self):
- self._Run(self._experiment)
- self._PrintTable(self._experiment)
- if not self._terminated:
- self._StoreResults(self._experiment)
- self._Email(self._experiment)
-
-
-class MockExperimentRunner(ExperimentRunner):
- """Mocked ExperimentRunner for testing."""
-
- def __init__(self, experiment):
- super(MockExperimentRunner, self).__init__(experiment)
-
- def _Run(self, experiment):
- self.l.LogOutput("Would run the following experiment: '%s'." %
- experiment.name)
-
- def _PrintTable(self, experiment):
- self.l.LogOutput("Would print the experiment table.")
-
- def _Email(self, experiment):
- self.l.LogOutput("Would send result email.")
-
- def _StoreResults(self, experiment):
- self.l.LogOutput("Would store the results.")
diff --git a/v14/crosperf/experiment_status.py b/v14/crosperf/experiment_status.py
deleted file mode 100644
index 3a270663..00000000
--- a/v14/crosperf/experiment_status.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-"""The class to show the banner."""
-
-import datetime
-import time
-
-
-class ExperimentStatus(object):
- """The status class."""
-
- def __init__(self, experiment):
- self.experiment = experiment
- self.num_total = len(self.experiment.benchmark_runs)
- self.completed = 0
- self.new_job_start_time = time.time()
-
- def _GetProgressBar(self, num_complete, num_total):
- ret = "Done: %s%%" % int(100.0 * num_complete / num_total)
- bar_length = 50
- done_char = ">"
- undone_char = " "
- num_complete_chars = bar_length * num_complete / num_total
- num_undone_chars = bar_length - num_complete_chars
- ret += " [%s%s]" % (num_complete_chars * done_char, num_undone_chars *
- undone_char)
- return ret
-
- def GetProgressString(self):
- """Get the elapsed_time, ETA."""
- current_time = time.time()
- if self.experiment.start_time:
- elapsed_time = current_time - self.experiment.start_time
- else:
- elapsed_time = 0
- try:
- if self.completed != self.experiment.num_complete:
- self.completed = self.experiment.num_complete
- self.new_job_start_time = current_time
- time_completed_jobs = (elapsed_time -
- (current_time - self.new_job_start_time))
- eta_seconds = (float(self.num_total - self.experiment.num_complete -1) *
- time_completed_jobs / self.experiment.num_run_complete
- + (time_completed_jobs / self.experiment.num_run_complete
- - (current_time - self.new_job_start_time)))
-
- eta_seconds = int(eta_seconds)
- eta = datetime.timedelta(seconds=eta_seconds)
- except ZeroDivisionError:
- eta = "Unknown"
- strings = []
- strings.append("Current time: %s Elapsed: %s ETA: %s" %
- (datetime.datetime.now(),
- datetime.timedelta(seconds=int(elapsed_time)),
- eta))
- strings.append(self._GetProgressBar(self.experiment.num_complete,
- self.num_total))
- return "\n".join(strings)
-
- def GetStatusString(self):
- """Get the status string of all the benchmark_runs."""
- status_bins = {}
- for benchmark_run in self.experiment.benchmark_runs:
- if benchmark_run.timeline.GetLastEvent() not in status_bins:
- status_bins[benchmark_run.timeline.GetLastEvent()] = []
- status_bins[benchmark_run.timeline.GetLastEvent()].append(benchmark_run)
-
- status_strings = []
- for key, val in status_bins.items():
- status_strings.append("%s: %s" %
- (key, self._GetNamesAndIterations(val)))
- result = "Thread Status:\n%s" % "\n".join(status_strings)
-
- # Add the machine manager status.
- result += "\n" + self.experiment.machine_manager.AsString() + "\n"
-
- return result
-
- def _GetNamesAndIterations(self, benchmark_runs):
- strings = []
- t = time.time()
- for benchmark_run in benchmark_runs:
- t_last = benchmark_run.timeline.GetLastEventTime()
- elapsed = str(datetime.timedelta(seconds=int(t-t_last)))
- strings.append("'{0}' {1}".format(benchmark_run.name, elapsed))
- return " %s (%s)" % (len(strings), ", ".join(strings))
diff --git a/v14/crosperf/field.py b/v14/crosperf/field.py
deleted file mode 100644
index b3cdaa23..00000000
--- a/v14/crosperf/field.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-
-class Field(object):
- """Class representing a Field in an experiment file."""
-
- def __init__(self, name, required, default, inheritable, description):
- self.name = name
- self.required = required
- self.assigned = False
- self.default = default
- self._value = default
- self.inheritable = inheritable
- self.description = description
-
- def Set(self, value, parse=True):
- if parse:
- self._value = self._Parse(value)
- else:
- self._value = value
- self.assigned = True
-
- def Append(self, value):
- self._value += self._Parse(value)
- self.assigned = True
-
- def _Parse(self, value):
- return value
-
- def Get(self):
- return self._value
-
- def GetString(self):
- return str(self._value)
-
-
-class TextField(Field):
- def __init__(self, name, required=False, default="", inheritable=False,
- description=""):
- super(TextField, self).__init__(name, required, default, inheritable,
- description)
-
- def _Parse(self, value):
- return str(value)
-
-
-class BooleanField(Field):
- def __init__(self, name, required=False, default=False, inheritable=False,
- description=""):
- super(BooleanField, self).__init__(name, required, default, inheritable,
- description)
-
- def _Parse(self, value):
- if value.lower() == "true":
- return True
- elif value.lower() == "false":
- return False
- raise Exception("Invalid value for '%s'. Must be true or false." %
- self.name)
-
-
-class IntegerField(Field):
- def __init__(self, name, required=False, default=0, inheritable=False,
- description=""):
- super(IntegerField, self).__init__(name, required, default, inheritable,
- description)
-
- def _Parse(self, value):
- return int(value)
-
-
-class FloatField(Field):
- def __init__(self, name, required=False, default=0, inheritable=False,
- description=""):
- super(FloatField, self).__init__(name, required, default, inheritable,
- description)
-
- def _Parse(self, value):
- return float(value)
-
-
-class ListField(Field):
- def __init__(self, name, required=False, default=[], inheritable=False,
- description=""):
- super(ListField, self).__init__(name, required, default, inheritable,
- description)
-
- def _Parse(self, value):
- return value.split()
-
- def GetString(self):
- return " ".join(self._value)
-
-
-class EnumField(Field):
- def __init__(self, name, options, required=False, default="",
- inheritable=False, description=""):
- super(EnumField, self).__init__(name, required, default, inheritable,
- description)
- self.options = options
-
- def _Parse(self, value):
- if value not in self.options:
- raise Exception("Invalid enum value for field '%s'. Must be one of (%s)"
- % (self.name, ", ".join(self.options)))
- return str(value)
diff --git a/v14/crosperf/help.py b/v14/crosperf/help.py
deleted file mode 100644
index cf74d93e..00000000
--- a/v14/crosperf/help.py
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-import sys
-import textwrap
-from settings_factory import BenchmarkSettings
-from settings_factory import GlobalSettings
-from settings_factory import LabelSettings
-
-
-class Help(object):
- def GetUsage(self):
- return """%s [OPTIONS] [ACTION] EXPERIMENT_FILE""" % (sys.argv[0])
-
- def _WrapLine(self, line):
- return "\n".join(textwrap.wrap(line, 80))
-
- def _GetFieldDescriptions(self, fields):
- res = ""
- for field_name in fields:
- field = fields[field_name]
- res += "Field:\t\t%s\n" % field.name
- res += self._WrapLine("Description:\t%s" % field.description) + "\n"
- res += "Type:\t\t%s\n" % type(field).__name__.replace("Field", "")
- res += "Required:\t%s\n" % field.required
- if field.default:
- res += "Default:\t%s\n" % field.default
- res += "\n"
- return res
-
- def GetHelp(self):
- global_fields = self._GetFieldDescriptions(GlobalSettings("").fields)
- benchmark_fields = self._GetFieldDescriptions(BenchmarkSettings("").fields)
- label_fields = self._GetFieldDescriptions(LabelSettings("").fields)
-
- return """%s is a script for running performance experiments on ChromeOS. It
-allows one to run ChromeOS Autotest benchmarks over several images and compare
-the results to determine whether there is a performance difference.
-
-Comparing several images using %s is referred to as running an
-"experiment". An "experiment file" is a configuration file which holds all the
-information that describes the experiment and how it should be run. An example
-of a simple experiment file is below:
-
---------------------------------- test.exp ---------------------------------
-name: my_experiment
-board: x86-alex
-remote: chromeos-alex5 172.18.122.132
-
-benchmark: PageCycler {
- iterations: 3
-}
-
-my_first_image {
- chromeos_image: /usr/local/chromeos-1/chromiumos_image.bin
-}
-
-my_second_image {
- chromeos_image: /usr/local/chromeos-2/chromiumos_image.bin
-}
-----------------------------------------------------------------------------
-
-This experiment file names the experiment "my_experiment". It will be run
-on the board x86-alex. Benchmarks will be run using two remote devices,
-one is a device specified by a hostname and the other is a device specified
-by it's IP address. Benchmarks will be run in parallel across these devices.
-There is currently no way to specify which benchmark will run on each device.
-
-We define one "benchmark" that will be run, PageCycler. This benchmark has one
-"field" which specifies how many iterations it will run for.
-
-We specify 2 "labels" or images which will be compared. The PageCycler benchmark
-will be run on each of these images 3 times and a result table will be output
-which compares the two.
-
-The full list of fields that can be specified are as follows:
-=================
-Global Fields
-=================
-%s
-=================
-Benchmark Fields
-=================
-%s
-=================
-Label Fields
-=================
-%s
-
-Note that global fields are overidden by label or benchmark fields, if they can
-be specified in both places. Fields that are specified as arguments override
-fields specified in experiment files.
-
-%s is invoked by passing it a path to an experiment file, as well as an action
-to execute on that experiment file. The possible actions to use are:
-
-run\t\tRun the experiment and cache the results.
-
-table\t\tDisplay cached results of an experiment, without running anything.
-
-email\t\tEmail a summary of the results to the user.
-
-do\t\tThe default action. Executes the following actions: run, table, email.
-""" % (sys.argv[0], sys.argv[0], global_fields,
- benchmark_fields, label_fields, sys.argv[0])
diff --git a/v14/crosperf/image_checksummer.py b/v14/crosperf/image_checksummer.py
deleted file mode 100644
index dcc1cb02..00000000
--- a/v14/crosperf/image_checksummer.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-import os
-import threading
-
-from utils import logger
-from utils.file_utils import FileUtils
-
-
-class ImageChecksummer(object):
- class PerImageChecksummer(object):
- def __init__(self, label):
- self._lock = threading.Lock()
- self.label = label
- self._checksum = None
-
- def Checksum(self):
- with self._lock:
- if not self._checksum:
- logger.GetLogger().LogOutput("Acquiring checksum for '%s'." %
- self.label.name)
- self._checksum = None
- if self.label.chromeos_image:
- if os.path.exists(self.label.chromeos_image):
- self._checksum = FileUtils().Md5File(self.label.chromeos_image)
- logger.GetLogger().LogOutput("Computed checksum is "
- ": %s" % self._checksum)
- if not self._checksum:
- if self.label.image_md5sum:
- self._checksum = self.label.image_md5sum
- logger.GetLogger().LogOutput("Checksum in experiment file is "
- ": %s" % self._checksum)
- else:
- raise Exception("Checksum computing error.")
- logger.GetLogger().LogOutput("Checksum is: %s" % self._checksum)
- return self._checksum
-
- _instance = None
- _lock = threading.Lock()
- _per_image_checksummers = {}
-
- def __new__(cls, *args, **kwargs):
- with cls._lock:
- if not cls._instance:
- cls._instance = super(ImageChecksummer, cls).__new__(cls,
- *args, **kwargs)
- return cls._instance
-
- def Checksum(self, label):
- with self._lock:
- if label.name not in self._per_image_checksummers:
- self._per_image_checksummers[label.name] = (ImageChecksummer.
- PerImageChecksummer(label))
- checksummer = self._per_image_checksummers[label.name]
-
- try:
- return checksummer.Checksum()
- except Exception, e:
- logger.GetLogger().LogError("Could not compute checksum of image in label"
- " '%s'."% label.name)
- raise e
diff --git a/v14/crosperf/label.py b/v14/crosperf/label.py
deleted file mode 100644
index be7a868e..00000000
--- a/v14/crosperf/label.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-"""The label of benchamrks."""
-
-import os
-from utils.file_utils import FileUtils
-
-
-class Label(object):
- def __init__(self, name, chromeos_image, chromeos_root, board, remote,
- image_args, image_md5sum, cache_dir):
- # Expand ~
- chromeos_root = os.path.expanduser(chromeos_root)
- chromeos_image = os.path.expanduser(chromeos_image)
-
- self.name = name
- self.chromeos_image = chromeos_image
- self.board = board
- self.remote = remote
- self.image_args = image_args
- self.image_md5sum = image_md5sum
- self.cache_dir = cache_dir
-
- if not chromeos_root:
- chromeos_root = FileUtils().ChromeOSRootFromImage(chromeos_image)
- if not chromeos_root:
- raise Exception("No ChromeOS root given for label '%s' and could not "
- "determine one from image path: '%s'." %
- (name, chromeos_image))
- else:
- chromeos_root = FileUtils().CanonicalizeChromeOSRoot(chromeos_root)
- if not chromeos_root:
- raise Exception("Invalid ChromeOS root given for label '%s': '%s'."
- % (name, chromeos_root))
-
- self.chromeos_root = chromeos_root
-
-
-class MockLabel(object):
- def __init__(self, name, chromeos_image, chromeos_root, board, remote,
- image_args, image_md5sum, cache_dir):
- self.name = name
- self.chromeos_image = chromeos_image
- self.board = board
- self.remote = remote
- self.cache_dir = cache_dir
- if not chromeos_root:
- self.chromeos_root = "/tmp/chromeos_root"
- else:
- self.chromeos_root = chromeos_root
- self.image_args = image_args
- self.image_md5sum = image_md5sum
diff --git a/v14/crosperf/machine_manager.py b/v14/crosperf/machine_manager.py
deleted file mode 100644
index 29a4df7a..00000000
--- a/v14/crosperf/machine_manager.py
+++ /dev/null
@@ -1,419 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2012 Google Inc. All Rights Reserved.
-
-import hashlib
-import image_chromeos
-import lock_machine
-import math
-import os.path
-import re
-import sys
-import threading
-import time
-
-from utils import command_executer
-from utils import logger
-from utils.file_utils import FileUtils
-
-from image_checksummer import ImageChecksummer
-
-CHECKSUM_FILE = "/usr/local/osimage_checksum_file"
-
-
-class CrosMachine(object):
- def __init__(self, name, chromeos_root):
- self.name = name
- self.image = None
- self.checksum = None
- self.locked = False
- self.released_time = time.time()
- self.autotest_run = None
- self.chromeos_root = chromeos_root
- self._GetMemoryInfo()
- self._GetCPUInfo()
- self._ComputeMachineChecksumString()
- self._GetMachineID()
- self.machine_checksum = self._GetMD5Checksum(self.checksum_string)
- self.machine_id_checksum = self._GetMD5Checksum(self.machine_id)
-
- def _ParseMemoryInfo(self):
- line = self.meminfo.splitlines()[0]
- usable_kbytes = int(line.split()[1])
- # This code is from src/third_party/autotest/files/client/bin/base_utils.py
- # usable_kbytes is system's usable DRAM in kbytes,
- # as reported by memtotal() from device /proc/meminfo memtotal
- # after Linux deducts 1.5% to 9.5% for system table overhead
- # Undo the unknown actual deduction by rounding up
- # to next small multiple of a big power-of-two
- # eg 12GB - 5.1% gets rounded back up to 12GB
- mindeduct = 0.005 # 0.5 percent
- maxdeduct = 0.095 # 9.5 percent
- # deduction range 1.5% .. 9.5% supports physical mem sizes
- # 6GB .. 12GB in steps of .5GB
- # 12GB .. 24GB in steps of 1 GB
- # 24GB .. 48GB in steps of 2 GB ...
- # Finer granularity in physical mem sizes would require
- # tighter spread between min and max possible deductions
-
- # increase mem size by at least min deduction, without rounding
- min_kbytes = int(usable_kbytes / (1.0 - mindeduct))
- # increase mem size further by 2**n rounding, by 0..roundKb or more
- round_kbytes = int(usable_kbytes / (1.0 - maxdeduct)) - min_kbytes
- # find least binary roundup 2**n that covers worst-cast roundKb
- mod2n = 1 << int(math.ceil(math.log(round_kbytes, 2)))
- # have round_kbytes <= mod2n < round_kbytes*2
- # round min_kbytes up to next multiple of mod2n
- phys_kbytes = min_kbytes + mod2n - 1
- phys_kbytes -= phys_kbytes % mod2n # clear low bits
- self.phys_kbytes = phys_kbytes
-
- def _GetMemoryInfo(self):
- #TODO yunlian: when the machine in rebooting, it will not return
- #meminfo, the assert does not catch it either
- ce = command_executer.GetCommandExecuter()
- command = "cat /proc/meminfo"
- ret, self.meminfo, _ = ce.CrosRunCommand(
- command, return_output=True,
- machine=self.name, username="root", chromeos_root=self.chromeos_root)
- assert ret == 0, "Could not get meminfo from machine: %s" % self.name
- if ret == 0:
- self._ParseMemoryInfo()
-
- #cpuinfo format is different across architecture
- #need to find a better way to parse it.
- def _ParseCPUInfo(self,cpuinfo):
- return 0
-
- def _GetCPUInfo(self):
- ce = command_executer.GetCommandExecuter()
- command = "cat /proc/cpuinfo"
- ret, self.cpuinfo, _ = ce.CrosRunCommand(
- command, return_output=True,
- machine=self.name, username="root", chromeos_root=self.chromeos_root)
- assert ret == 0, "Could not get cpuinfo from machine: %s" % self.name
- if ret == 0:
- self._ParseCPUInfo(self.cpuinfo)
-
- def _ComputeMachineChecksumString(self):
- self.checksum_string = ""
- exclude_lines_list = ["MHz", "BogoMIPS", "bogomips"]
- for line in self.cpuinfo.splitlines():
- if not any([e in line for e in exclude_lines_list]):
- self.checksum_string += line
- self.checksum_string += " " + str(self.phys_kbytes)
-
- def _GetMD5Checksum(self, ss):
- if ss:
- return hashlib.md5(ss).hexdigest()
- else:
- return ""
-
- def _GetMachineID(self):
- ce = command_executer.GetCommandExecuter()
- command = "dump_vpd_log --full --stdout"
- ret, if_out, _ = ce.CrosRunCommand(
- command, return_output=True,
- machine=self.name, chromeos_root=self.chromeos_root)
- b = if_out.splitlines()
- a = [l for l in b if "Product" in l]
- self.machine_id = a[0]
- assert ret == 0, "Could not get machine_id from machine: %s" % self.name
-
- def __str__(self):
- l = []
- l.append(self.name)
- l.append(str(self.image))
- l.append(str(self.checksum))
- l.append(str(self.locked))
- l.append(str(self.released_time))
- return ", ".join(l)
-
-
-class MachineManager(object):
- def __init__(self, chromeos_root, acquire_timeout):
- self._lock = threading.RLock()
- self._all_machines = []
- self._machines = []
- self.image_lock = threading.Lock()
- self.num_reimages = 0
- self.chromeos_root = None
- self.machine_checksum = {}
- self.machine_checksum_string = {}
- self.acquire_timeout = acquire_timeout
-
- if os.path.isdir(lock_machine.Machine.LOCKS_DIR):
- self.no_lock = False
- else:
- self.no_lock = True
- self._initialized_machines = []
- self.chromeos_root = chromeos_root
-
- def ImageMachine(self, machine, label):
- checksum = ImageChecksummer().Checksum(label)
- if machine.checksum == checksum:
- return
- chromeos_root = label.chromeos_root
- if not chromeos_root:
- chromeos_root = self.chromeos_root
- image_chromeos_args = [image_chromeos.__file__,
- "--chromeos_root=%s" % chromeos_root,
- "--image=%s" % label.chromeos_image,
- "--image_args=%s" % label.image_args,
- "--remote=%s" % machine.name]
- if label.board:
- image_chromeos_args.append("--board=%s" % label.board)
-
- # Currently can't image two machines at once.
- # So have to serialized on this lock.
- ce = command_executer.GetCommandExecuter()
- with self.image_lock:
- retval = ce.RunCommand(" ".join(["python"] + image_chromeos_args))
- if retval:
- raise Exception("Could not image machine: '%s'." % machine.name)
- else:
- self.num_reimages += 1
- machine.checksum = checksum
- machine.image = label.chromeos_image
-
- return retval
-
- def ComputeCommonCheckSum(self, label):
- for machine in self.GetMachines(label):
- if machine.machine_checksum:
- self.machine_checksum[label.name] = machine.machine_checksum
- break
-
- def ComputeCommonCheckSumString(self, label):
- for machine in self.GetMachines(label):
- if machine.checksum_string:
- self.machine_checksum_string[label.name] = machine.checksum_string
- break
-
- def _TryToLockMachine(self, cros_machine):
- with self._lock:
- assert cros_machine, "Machine can't be None"
- for m in self._machines:
- if m.name == cros_machine.name:
- return
- if self.no_lock:
- locked = True
- else:
- locked = lock_machine.Machine(cros_machine.name).Lock(True, sys.argv[0])
- if locked:
- self._machines.append(cros_machine)
- ce = command_executer.GetCommandExecuter()
- command = "cat %s" % CHECKSUM_FILE
- ret, out, _ = ce.CrosRunCommand(
- command, return_output=True, chromeos_root=self.chromeos_root,
- machine=cros_machine.name)
- if ret == 0:
- cros_machine.checksum = out.strip()
- else:
- logger.GetLogger().LogOutput("Couldn't lock: %s" % cros_machine.name)
-
- # This is called from single threaded mode.
- def AddMachine(self, machine_name):
- with self._lock:
- for m in self._all_machines:
- assert m.name != machine_name, "Tried to double-add %s" % machine_name
- cm = CrosMachine(machine_name, self.chromeos_root)
- assert cm.machine_checksum, ("Could not find checksum for machine %s" %
- machine_name)
- self._all_machines.append(cm)
-
- def AreAllMachineSame(self, label):
- checksums = [m.machine_checksum for m in self.GetMachines(label)]
- return len(set(checksums)) == 1
-
- def AcquireMachine(self, chromeos_image, label):
- image_checksum = ImageChecksummer().Checksum(label)
- machines = self.GetMachines(label)
- check_interval_time = 120
- with self._lock:
- # Lazily external lock machines
- while self.acquire_timeout >= 0:
- for m in machines:
- new_machine = m not in self._all_machines
- self._TryToLockMachine(m)
- if new_machine:
- m.released_time = time.time()
- if not self.AreAllMachineSame(label):
- logger.GetLogger().LogFatal("-- not all the machine are identical")
- if self.GetAvailableMachines(label):
- break
- else:
- sleep_time = max(1, min(self.acquire_timeout, check_interval_time))
- time.sleep(sleep_time)
- self.acquire_timeout -= sleep_time
-
- if self.acquire_timeout < 0:
- machine_names = []
- for machine in machines:
- machine_names.append(machine.name)
- logger.GetLogger().LogFatal("Could not acquire any of the "
- "following machines: '%s'"
- % ", ".join(machine_names))
-
-### for m in self._machines:
-### if (m.locked and time.time() - m.released_time < 10 and
-### m.checksum == image_checksum):
-### return None
- for m in [machine for machine in self.GetAvailableMachines(label)
- if not machine.locked]:
- if m.checksum == image_checksum:
- m.locked = True
- m.autotest_run = threading.current_thread()
- return m
- for m in [machine for machine in self.GetAvailableMachines(label)
- if not machine.locked]:
- if not m.checksum:
- m.locked = True
- m.autotest_run = threading.current_thread()
- return m
- # This logic ensures that threads waiting on a machine will get a machine
- # with a checksum equal to their image over other threads. This saves time
- # when crosperf initially assigns the machines to threads by minimizing
- # the number of re-images.
- # TODO(asharif): If we centralize the thread-scheduler, we wont need this
- # code and can implement minimal reimaging code more cleanly.
- for m in [machine for machine in self.GetAvailableMachines(label)
- if not machine.locked]:
- if time.time() - m.released_time > 20:
- m.locked = True
- m.autotest_run = threading.current_thread()
- return m
- return None
-
- def GetAvailableMachines(self, label=None):
- if not label:
- return self._machines
- return [m for m in self._machines if m.name in label.remote]
-
- def GetMachines(self, label=None):
- if not label:
- return self._all_machines
- return [m for m in self._all_machines if m.name in label.remote]
-
- def ReleaseMachine(self, machine):
- with self._lock:
- for m in self._machines:
- if machine.name == m.name:
- assert m.locked == True, "Tried to double-release %s" % m.name
- m.released_time = time.time()
- m.locked = False
- m.status = "Available"
- break
-
- def Cleanup(self):
- with self._lock:
- # Unlock all machines.
- for m in self._machines:
- if not self.no_lock:
- res = lock_machine.Machine(m.name).Unlock(True)
- if not res:
- logger.GetLogger().LogError("Could not unlock machine: '%s'."
- % m.name)
-
- def __str__(self):
- with self._lock:
- l = ["MachineManager Status:"]
- for m in self._machines:
- l.append(str(m))
- return "\n".join(l)
-
- def AsString(self):
- with self._lock:
- stringify_fmt = "%-30s %-10s %-4s %-25s %-32s"
- header = stringify_fmt % ("Machine", "Thread", "Lock", "Status",
- "Checksum")
- table = [header]
- for m in self._machines:
- if m.autotest_run:
- autotest_name = m.autotest_run.name
- autotest_status = m.autotest_run.timeline.GetLastEvent()
- else:
- autotest_name = ""
- autotest_status = ""
-
- try:
- machine_string = stringify_fmt % (m.name,
- autotest_name,
- m.locked,
- autotest_status,
- m.checksum)
- except Exception:
- machine_string = ""
- table.append(machine_string)
- return "Machine Status:\n%s" % "\n".join(table)
-
- def GetAllCPUInfo(self, labels):
- """Get cpuinfo for labels, merge them if their cpuinfo are the same."""
- dic = {}
- for label in labels:
- for machine in self._all_machines:
- if machine.name in label.remote:
- if machine.cpuinfo not in dic:
- dic[machine.cpuinfo] = [label.name]
- else:
- dic[machine.cpuinfo].append(label.name)
- break
- output = ""
- for key, v in dic.items():
- output += " ".join(v)
- output += "\n-------------------\n"
- output += key
- output += "\n\n\n"
- return output
-
-
-class MockCrosMachine(CrosMachine):
- def __init__(self, name, chromeos_root):
- self.name = name
- self.image = None
- self.checksum = None
- self.locked = False
- self.released_time = time.time()
- self.autotest_run = None
- self.chromeos_root = chromeos_root
- self.checksum_string = re.sub("\d", "", name)
- #In test, we assume "lumpy1", "lumpy2" are the same machine.
- self.machine_checksum = self._GetMD5Checksum(self.checksum_string)
-
-
-class MockMachineManager(MachineManager):
-
- def __init__(self, chromeos_root, acquire_timeout):
- super(MockMachineManager, self).__init__(chromeos_root, acquire_timeout)
-
- def _TryToLockMachine(self, cros_machine):
- self._machines.append(cros_machine)
- cros_machine.checksum = ""
-
- def AddMachine(self, machine_name):
- with self._lock:
- for m in self._all_machines:
- assert m.name != machine_name, "Tried to double-add %s" % machine_name
- cm = MockCrosMachine(machine_name, self.chromeos_root)
- assert cm.machine_checksum, ("Could not find checksum for machine %s" %
- machine_name)
- self._all_machines.append(cm)
-
- def AcquireMachine(self, chromeos_image, label):
- for machine in self._all_machines:
- if not machine.locked:
- machine.locked = True
- return machine
- return None
-
- def ImageMachine(self, machine_name, label):
- return 0
-
- def ReleaseMachine(self, machine):
- machine.locked = False
-
- def GetMachines(self, label):
- return self._all_machines
-
- def GetAvailableMachines(self, label):
- return self._all_machines
diff --git a/v14/crosperf/machine_manager_unittest.py b/v14/crosperf/machine_manager_unittest.py
deleted file mode 100755
index 84266d5e..00000000
--- a/v14/crosperf/machine_manager_unittest.py
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2012 Google Inc. All Rights Reserved.
-
-"""Unittest for machine_manager."""
-import unittest
-
-import label
-import machine_manager
-
-
-class MyMachineManager(machine_manager.MachineManager):
-
- def __init__(self, chromeos_root):
- super(MyMachineManager, self).__init__(chromeos_root, 0)
-
- def _TryToLockMachine(self, cros_machine):
- self._machines.append(cros_machine)
- cros_machine.checksum = ""
-
- def AddMachine(self, machine_name):
- with self._lock:
- for m in self._all_machines:
- assert m.name != machine_name, "Tried to double-add %s" % machine_name
- cm = machine_manager.MockCrosMachine(machine_name, self.chromeos_root)
- assert cm.machine_checksum, ("Could not find checksum for machine %s" %
- machine_name)
- self._all_machines.append(cm)
-
-CHROMEOS_ROOT = "/tmp/chromeos-root"
-MACHINE_NAMES = ["lumpy1", "lumpy2", "lumpy3", "daisy1", "daisy2"]
-LABEL_LUMPY = label.MockLabel("lumpy", "image", CHROMEOS_ROOT, "lumpy",
- ["lumpy1", "lumpy2", "lumpy3", "lumpy4"],
- "", "", "")
-LABEL_MIX = label.MockLabel("mix", "image", CHROMEOS_ROOT, "mix",
- ["daisy1", "daisy2", "lumpy3", "lumpy4"],
- "", "", "")
-
-
-class MachineManagerTest(unittest.TestCase):
-
- def testAreAllMachineSame(self):
- manager = MyMachineManager(CHROMEOS_ROOT)
- for m in MACHINE_NAMES:
- manager.AddMachine(m)
- self.assertEqual(manager.AreAllMachineSame(LABEL_LUMPY), True)
- self.assertEqual(manager.AreAllMachineSame(LABEL_MIX), False)
-
- def testGetMachines(self):
- manager = MyMachineManager(CHROMEOS_ROOT)
- for m in MACHINE_NAMES:
- manager.AddMachine(m)
- names = [m.name for m in manager.GetMachines(LABEL_LUMPY)]
- self.assertEqual(names, ["lumpy1", "lumpy2", "lumpy3"])
-
- def testGetAvailableMachines(self):
- manager = MyMachineManager(CHROMEOS_ROOT)
- for m in MACHINE_NAMES:
- manager.AddMachine(m)
- for m in manager._all_machines:
- if int(m.name[-1]) % 2:
- manager._TryToLockMachine(m)
- names = [m.name for m in manager.GetAvailableMachines(LABEL_LUMPY)]
- self.assertEqual(names, ["lumpy1", "lumpy3"])
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/v14/crosperf/perf_table.py b/v14/crosperf/perf_table.py
deleted file mode 100644
index 3c8b88b8..00000000
--- a/v14/crosperf/perf_table.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2012 Google Inc. All Rights Reserved.
-"""Parse perf report data for tabulator."""
-
-import os
-
-from utils import perf_diff
-
-
-def ParsePerfReport(perf_file):
- """It should return a dict."""
-
- return {"cycles": {"foo": 10, "bar": 20},
- "cache_miss": {"foo": 20, "bar": 10}}
-
-
-class PerfTable(object):
- """The class to generate dicts for tabulator."""
-
- def __init__(self, experiment, label_names):
- self._experiment = experiment
- self._label_names = label_names
- self.perf_data = {}
- self.GenerateData()
-
- # {benchmark:{perf_event1:[[{func1:number, func2:number,
- # rows_to_show: number}
- # {func1: number, func2: number
- # rows_to_show: number}]], ...},
- # benchmark2:...}
- # The rows_to_show is temp data recording how many
- # rows have over 1% running time.
- self.row_info = {}
- self.GetRowsToShow()
-
- def GenerateData(self):
- for label in self._label_names:
- for benchmark in self._experiment.benchmarks:
- for i in range(1, benchmark.iterations+1):
- dir_name = label + benchmark.name + str(i)
- dir_name = filter(str.isalnum, dir_name)
- perf_file = os.path.join(self._experiment.results_directory,
- dir_name,
- "perf.data.report.0")
- self.ReadPerfReport(perf_file, label, benchmark.name, i - 1)
-
- def ReadPerfReport(self, perf_file, label, benchmark_name, iteration):
- """Add the data from one run to the dict."""
- if os.path.isfile(perf_file):
- perf_of_run = perf_diff.GetPerfDictFromReport(perf_file)
- else:
- perf_of_run = {}
- if benchmark_name not in self.perf_data:
- self.perf_data[benchmark_name] = {}
- for event in perf_of_run:
- self.perf_data[benchmark_name][event] = []
- ben_data = self.perf_data[benchmark_name]
-
- label_index = self._label_names.index(label)
- for event in ben_data:
- while len(ben_data[event]) <= label_index:
- ben_data[event].append([])
- data_for_label = ben_data[event][label_index]
- while len(data_for_label) <= iteration:
- data_for_label.append({})
- if perf_of_run:
- data_for_label[iteration] = perf_of_run[event]
- else:
- data_for_label[iteration] = {}
-
- def GetRowsToShow(self):
- for benchmark in self.perf_data:
- if benchmark not in self.row_info:
- self.row_info[benchmark] = {}
- for event in self.perf_data[benchmark]:
- rows = 0
- for run in self.perf_data[benchmark][event]:
- for iteration in run:
- if perf_diff.ROWS_TO_SHOW in iteration:
- rows = max(iteration[perf_diff.ROWS_TO_SHOW], rows)
- # delete the temp data which stores how many rows of
- # the perf data have over 1% running time.
- del iteration[perf_diff.ROWS_TO_SHOW]
- self.row_info[benchmark][event] = rows
diff --git a/v14/crosperf/results_cache.py b/v14/crosperf/results_cache.py
deleted file mode 100644
index 0357275d..00000000
--- a/v14/crosperf/results_cache.py
+++ /dev/null
@@ -1,417 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-import getpass
-import glob
-import hashlib
-import os
-import pickle
-import re
-import tempfile
-
-from utils import command_executer
-from utils import misc
-
-from image_checksummer import ImageChecksummer
-
-SCRATCH_BASE = "/home/%s/cros_scratch"
-SCRATCH_DIR = SCRATCH_BASE % getpass.getuser()
-RESULTS_FILE = "results.txt"
-MACHINE_FILE = "machine.txt"
-AUTOTEST_TARBALL = "autotest.tbz2"
-PERF_RESULTS_FILE = "perf-results.txt"
-
-
-class Result(object):
- """ This class manages what exactly is stored inside the cache without knowing
- what the key of the cache is. For runs with perf, it stores perf.data,
- perf.report, etc. The key generation is handled by the ResultsCache class.
- """
-
- def __init__(self, chromeos_root, logger, label_name):
- self._chromeos_root = chromeos_root
- self._logger = logger
- self._ce = command_executer.GetCommandExecuter(self._logger)
- self._temp_dir = None
- self.label_name = label_name
-
- def _CopyFilesTo(self, dest_dir, files_to_copy):
- file_index = 0
- for file_to_copy in files_to_copy:
- if not os.path.isdir(dest_dir):
- command = "mkdir -p %s" % dest_dir
- self._ce.RunCommand(command)
- dest_file = os.path.join(dest_dir,
- ("%s.%s" % (os.path.basename(file_to_copy),
- file_index)))
- ret = self._ce.CopyFiles(file_to_copy,
- dest_file,
- recursive=False)
- if ret:
- raise Exception("Could not copy results file: %s" % file_to_copy)
-
- def CopyResultsTo(self, dest_dir):
- self._CopyFilesTo(dest_dir, self.perf_data_files)
- self._CopyFilesTo(dest_dir, self.perf_report_files)
-
- def _GetKeyvals(self):
- results_in_chroot = os.path.join(self._chromeos_root,
- "chroot", "tmp")
- if not self._temp_dir:
- self._temp_dir = tempfile.mkdtemp(dir=results_in_chroot)
- command = "cp -r {0}/* {1}".format(self.results_dir, self._temp_dir)
- self._ce.RunCommand(command)
-
- command = ("python generate_test_report --no-color --csv %s" %
- (os.path.join("/tmp", os.path.basename(self._temp_dir))))
- [_, out, _] = self._ce.ChrootRunCommand(self._chromeos_root,
- command,
- return_output=True)
- keyvals_dict = {}
- for line in out.splitlines():
- tokens = re.split("=|,", line)
- key = tokens[-2]
- if key.startswith(self.results_dir):
- key = key[len(self.results_dir) + 1:]
- value = tokens[-1]
- keyvals_dict[key] = value
-
- return keyvals_dict
-
- def _GetResultsDir(self):
- mo = re.search(r"Results placed in (\S+)", self.out)
- if mo:
- result = mo.group(1)
- return result
- raise Exception("Could not find results directory.")
-
- def _FindFilesInResultsDir(self, find_args):
- command = "find %s %s" % (self.results_dir,
- find_args)
- ret, out, _ = self._ce.RunCommand(command, return_output=True)
- if ret:
- raise Exception("Could not run find command!")
- return out
-
- def _GetPerfDataFiles(self):
- return self._FindFilesInResultsDir("-name perf.data").splitlines()
-
- def _GetPerfReportFiles(self):
- return self._FindFilesInResultsDir("-name perf.data.report").splitlines()
-
- def _GeneratePerfReportFiles(self):
- perf_report_files = []
- for perf_data_file in self.perf_data_files:
- # Generate a perf.report and store it side-by-side with the perf.data
- # file.
- chroot_perf_data_file = misc.GetInsideChrootPath(self._chromeos_root,
- perf_data_file)
- perf_report_file = "%s.report" % perf_data_file
- if os.path.exists(perf_report_file):
- raise Exception("Perf report file already exists: %s" %
- perf_report_file)
- chroot_perf_report_file = misc.GetInsideChrootPath(self._chromeos_root,
- perf_report_file)
- command = ("/usr/sbin/perf report "
- "-n "
- "--symfs /build/%s "
- "--vmlinux /build/%s/usr/lib/debug/boot/vmlinux "
- "--kallsyms /build/%s/boot/System.map-* "
- "-i %s --stdio "
- "> %s" %
- (self._board,
- self._board,
- self._board,
- chroot_perf_data_file,
- chroot_perf_report_file))
- self._ce.ChrootRunCommand(self._chromeos_root,
- command)
-
- # Add a keyval to the dictionary for the events captured.
- perf_report_files.append(
- misc.GetOutsideChrootPath(self._chromeos_root,
- chroot_perf_report_file))
- return perf_report_files
-
- def _GatherPerfResults(self):
- report_id = 0
- for perf_report_file in self.perf_report_files:
- with open(perf_report_file, "r") as f:
- report_contents = f.read()
- for group in re.findall(r"Events: (\S+) (\S+)", report_contents):
- num_events = group[0]
- event_name = group[1]
- key = "perf_%s_%s" % (report_id, event_name)
- value = str(misc.UnitToNumber(num_events))
- self.keyvals[key] = value
-
- def _PopulateFromRun(self, board, out, err, retval):
- self._board = board
- self.out = out
- self.err = err
- self.retval = retval
- self.chroot_results_dir = self._GetResultsDir()
- self.results_dir = misc.GetOutsideChrootPath(self._chromeos_root,
- self.chroot_results_dir)
- self.perf_data_files = self._GetPerfDataFiles()
- # Include all perf.report data in table.
- self.perf_report_files = self._GeneratePerfReportFiles()
- # TODO(asharif): Do something similar with perf stat.
-
- # Grab keyvals from the directory.
- self._ProcessResults()
-
- def _ProcessResults(self):
- # Note that this function doesn't know anything about whether there is a
- # cache hit or miss. It should process results agnostic of the cache hit
- # state.
- self.keyvals = self._GetKeyvals()
- self.keyvals["retval"] = self.retval
- # Generate report from all perf.data files.
- # Now parse all perf report files and include them in keyvals.
- self._GatherPerfResults()
-
- def _PopulateFromCacheDir(self, cache_dir):
- # Read in everything from the cache directory.
- with open(os.path.join(cache_dir, RESULTS_FILE), "r") as f:
- self.out = pickle.load(f)
- self.err = pickle.load(f)
- self.retval = pickle.load(f)
-
- # Untar the tarball to a temporary directory
- self._temp_dir = tempfile.mkdtemp(dir=os.path.join(self._chromeos_root,
- "chroot", "tmp"))
-
- command = ("cd %s && tar xf %s" %
- (self._temp_dir,
- os.path.join(cache_dir, AUTOTEST_TARBALL)))
- ret = self._ce.RunCommand(command)
- if ret:
- raise Exception("Could not untar cached tarball")
- self.results_dir = self._temp_dir
- self.perf_data_files = self._GetPerfDataFiles()
- self.perf_report_files = self._GetPerfReportFiles()
- self._ProcessResults()
-
- def CleanUp(self, rm_chroot_tmp):
- if rm_chroot_tmp:
- command = "rm -rf %s" % self.results_dir
- self._ce.RunCommand(command)
- if self._temp_dir:
- command = "rm -rf %s" % self._temp_dir
- self._ce.RunCommand(command)
-
- def StoreToCacheDir(self, cache_dir, machine_manager):
- # Create the dir if it doesn't exist.
- temp_dir = tempfile.mkdtemp()
-
- # Store to the temp directory.
- with open(os.path.join(temp_dir, RESULTS_FILE), "w") as f:
- pickle.dump(self.out, f)
- pickle.dump(self.err, f)
- pickle.dump(self.retval, f)
-
- tarball = os.path.join(temp_dir, AUTOTEST_TARBALL)
- command = ("cd %s && "
- "tar "
- "--exclude=var/spool "
- "--exclude=var/log "
- "-cjf %s ." % (self.results_dir, tarball))
- ret = self._ce.RunCommand(command)
- if ret:
- raise Exception("Couldn't store autotest output directory.")
- # Store machine info.
- # TODO(asharif): Make machine_manager a singleton, and don't pass it into
- # this function.
- with open(os.path.join(temp_dir, MACHINE_FILE), "w") as f:
- f.write(machine_manager.machine_checksum_string[self.label_name])
-
- if os.path.exists(cache_dir):
- command = "rm -rf {0}".format(cache_dir)
- self._ce.RunCommand(command)
-
- command = "mkdir -p {0} && ".format(os.path.dirname(cache_dir))
- command += "mv {0} {1}".format(temp_dir, cache_dir)
- ret = self._ce.RunCommand(command)
- if ret:
- command = "rm -rf {0}".format(temp_dir)
- self._ce.RunCommand(command)
- raise Exception("Could not move dir %s to dir %s" %
- (temp_dir, cache_dir))
-
- @classmethod
- def CreateFromRun(cls, logger, chromeos_root, board, label_name,
- out, err, retval):
- result = cls(chromeos_root, logger, label_name)
- result._PopulateFromRun(board, out, err, retval)
- return result
-
- @classmethod
- def CreateFromCacheHit(cls, chromeos_root, logger, cache_dir, label_name):
- result = cls(chromeos_root, logger, label_name)
- try:
- result._PopulateFromCacheDir(cache_dir)
- except Exception as e:
- logger.LogError("Exception while using cache: %s" % e)
- return None
- return result
-
-
-class CacheConditions(object):
- # Cache hit only if the result file exists.
- CACHE_FILE_EXISTS = 0
-
- # Cache hit if the checksum of cpuinfo and totalmem of
- # the cached result and the new run match.
- MACHINES_MATCH = 1
-
- # Cache hit if the image checksum of the cached result and the new run match.
- CHECKSUMS_MATCH = 2
-
- # Cache hit only if the cached result was successful
- RUN_SUCCEEDED = 3
-
- # Never a cache hit.
- FALSE = 4
-
- # Cache hit if the image path matches the cached image path.
- IMAGE_PATH_MATCH = 5
-
- # Cache hit if the uuid of hard disk mataches the cached one
-
- SAME_MACHINE_MATCH = 6
-
-
-class ResultsCache(object):
- """ This class manages the key of the cached runs without worrying about what
- is exactly stored (value). The value generation is handled by the Results
- class.
- """
- CACHE_VERSION = 6
-
- def Init(self, chromeos_image, chromeos_root, autotest_name, iteration,
- autotest_args, machine_manager, board, cache_conditions,
- logger_to_use, label, share_users):
- self.chromeos_image = chromeos_image
- self.chromeos_root = chromeos_root
- self.autotest_name = autotest_name
- self.iteration = iteration
- self.autotest_args = autotest_args,
- self.board = board
- self.cache_conditions = cache_conditions
- self.machine_manager = machine_manager
- self._logger = logger_to_use
- self._ce = command_executer.GetCommandExecuter(self._logger)
- self.label = label
- self.share_users = share_users
-
- def _GetCacheDirForRead(self):
- matching_dirs = []
- for glob_path in self._FormCacheDir(self._GetCacheKeyList(True)):
- matching_dirs += glob.glob(glob_path)
-
- if matching_dirs:
- # Cache file found.
- return matching_dirs[0]
- else:
- return None
-
- def _GetCacheDirForWrite(self):
- return self._FormCacheDir(self._GetCacheKeyList(False))[0]
-
- def _FormCacheDir(self, list_of_strings):
- cache_key = " ".join(list_of_strings)
- cache_dir = misc.GetFilenameFromString(cache_key)
- if self.label.cache_dir:
- cache_home = os.path.abspath(os.path.expanduser(self.label.cache_dir))
- cache_path = [os.path.join(cache_home, cache_dir)]
- else:
- cache_path = [os.path.join(SCRATCH_DIR, cache_dir)]
-
- for i in [x.strip() for x in self.share_users.split(",")]:
- path = SCRATCH_BASE % i
- cache_path.append(os.path.join(path, cache_dir))
-
- return cache_path
-
- def _GetCacheKeyList(self, read):
- if read and CacheConditions.MACHINES_MATCH not in self.cache_conditions:
- machine_checksum = "*"
- else:
- machine_checksum = self.machine_manager.machine_checksum[self.label.name]
- if read and CacheConditions.CHECKSUMS_MATCH not in self.cache_conditions:
- checksum = "*"
- else:
- checksum = ImageChecksummer().Checksum(self.label)
-
- if read and CacheConditions.IMAGE_PATH_MATCH not in self.cache_conditions:
- image_path_checksum = "*"
- else:
- image_path_checksum = hashlib.md5(self.chromeos_image).hexdigest()
-
- if read and CacheConditions.SAME_MACHINE_MATCH not in self.cache_conditions:
- machine_id_checksum = "*"
- else:
- for machine in self.machine_manager.GetMachines(self.label):
- if machine.name == self.label.remote[0]:
- machine_id_checksum = machine.machine_id_checksum
- break
-
- autotest_args_checksum = hashlib.md5(
- "".join(self.autotest_args)).hexdigest()
- return (image_path_checksum,
- self.autotest_name, str(self.iteration),
- autotest_args_checksum,
- checksum,
- machine_checksum,
- machine_id_checksum,
- str(self.CACHE_VERSION))
-
- def ReadResult(self):
- if CacheConditions.FALSE in self.cache_conditions:
- return None
- cache_dir = self._GetCacheDirForRead()
-
- if not cache_dir:
- return None
-
- if not os.path.isdir(cache_dir):
- return None
-
- self._logger.LogOutput("Trying to read from cache dir: %s" % cache_dir)
-
- result = Result.CreateFromCacheHit(self.chromeos_root,
- self._logger, cache_dir, self.label.name)
-
- if not result:
- return None
-
- if (result.retval == 0 or
- CacheConditions.RUN_SUCCEEDED not in self.cache_conditions):
- return result
-
- return None
-
- def StoreResult(self, result):
- cache_dir = self._GetCacheDirForWrite()
- result.StoreToCacheDir(cache_dir, self.machine_manager)
-
-
-class MockResultsCache(ResultsCache):
- def Init(self, *args):
- pass
-
- def ReadResult(self):
- return None
-
- def StoreResult(self, result):
- pass
-
-
-class MockResult(Result):
- def _PopulateFromRun(self, out, err, retval):
- self.out = out
- self.err = err
- self.retval = retval
-
diff --git a/v14/crosperf/results_organizer.py b/v14/crosperf/results_organizer.py
deleted file mode 100644
index 2e5c9296..00000000
--- a/v14/crosperf/results_organizer.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2012 Google Inc. All Rights Reserved.
-"""Parse data from benchmark_runs for tabulator."""
-import re
-
-
-class ResultOrganizer(object):
- """Create a dict from benchmark_runs.
-
- The structure of the output dict is as follows:
- {"benchmark_1":[
- [{"key1":"v1", "key2":"v2"},{"key1":"v1", "key2","v2"}]
- #one label
- []
- #the other label
- ]
- "benchmark_2":
- [
- ]}.
- """
- key_filter = ["milliseconds_",
- "retval",
- "iterations",
- "ms_",
- "score_"]
-
- def __init__(self, benchmark_runs, labels, benchmarks=None):
- self.result = {}
- self.labels = []
- self.prog = re.compile(r"(\w+)\{(\d+)\}")
- self.benchmarks = benchmarks
- if not self.benchmarks:
- self.benchmarks = []
- for label in labels:
- self.labels.append(label.name)
- for benchmark_run in benchmark_runs:
- benchmark_name = benchmark_run.benchmark.name
- if benchmark_name not in self.result:
- self.result[benchmark_name] = []
- while len(self.result[benchmark_name]) < len(labels):
- self.result[benchmark_name].append([])
- label_index = self.labels.index(benchmark_run.label.name)
- cur_table = self.result[benchmark_name][label_index]
- index = benchmark_run.iteration - 1
- while index >= len(cur_table):
- cur_table.append({})
- cur_dict = cur_table[index]
- if not benchmark_run.result:
- continue
- benchmark = benchmark_run.benchmark
- key_filter_on = (benchmark.key_results_only and
- "PyAutoPerfTest" in benchmark.name + benchmark.autotest_name and
- "perf." not in benchmark.autotest_args)
- for autotest_key in benchmark_run.result.keyvals:
- if (key_filter_on and
- not any([key for key in self.key_filter if key in autotest_key])
- ):
- continue
- result_value = benchmark_run.result.keyvals[autotest_key]
- cur_dict[autotest_key] = result_value
- self._DuplicatePass()
-
- def _DuplicatePass(self):
- for bench, data in self.result.items():
- max_dup = self._GetMaxDup(data)
- if not max_dup:
- continue
- for label in data:
- index = data.index(label)
- data[index] = self._GetNonDupLabel(max_dup, label)
- self._AdjustIteration(max_dup, bench)
-
- def _GetMaxDup(self, data):
- """Find the maximum i inside ABCD{i}."""
- max_dup = 0
- for label in data:
- for run in label:
- for key in run:
- if re.match(self.prog, key):
- max_dup = max(max_dup,
- int(re.search(self.prog, key).group(2)))
- return max_dup
-
- def _GetNonDupLabel(self, max_dup, label):
- """Create new list for the runs of the same label."""
- new_label = []
- for run in label:
- start_index = len(new_label)
- new_label.append(dict(run))
- for i in range(max_dup):
- new_label.append({})
- new_run = new_label[start_index]
- for key, value in new_run.items():
- if re.match(self.prog, key):
- new_key = re.search(self.prog, key).group(1)
- index = int(re.search(self.prog, key).group(2))
- new_label[start_index+index][new_key] = str(value)
- del new_run[key]
- return new_label
-
- def _AdjustIteration(self, max_dup, bench):
- """Adjust the interation numbers if the have keys like ABCD{i}."""
- for benchmark in self.benchmarks:
- if benchmark.name == bench:
- if not benchmark.iteration_adjusted:
- benchmark.iteration_adjusted = True
- benchmark.iterations *= (max_dup +1)
diff --git a/v14/crosperf/results_report.py b/v14/crosperf/results_report.py
deleted file mode 100644
index 61c67d5b..00000000
--- a/v14/crosperf/results_report.py
+++ /dev/null
@@ -1,502 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-from utils.tabulator import *
-
-from column_chart import ColumnChart
-from results_organizer import ResultOrganizer
-from perf_table import PerfTable
-
-
-class ResultsReport(object):
- MAX_COLOR_CODE = 255
- PERF_ROWS = 5
-
- def __init__(self, experiment):
- self.experiment = experiment
- self.benchmark_runs = experiment.benchmark_runs
- self.labels = experiment.labels
- self.benchmarks = experiment.benchmarks
- self.baseline = self.labels[0]
-
- def _SortByLabel(self, runs):
- labels = {}
- for benchmark_run in runs:
- if benchmark_run.label_name not in labels:
- labels[benchmark_run.label_name] = []
- labels[benchmark_run.label_name].append(benchmark_run)
- return labels
-
- def GetFullTables(self, perf=False):
- columns = [Column(NonEmptyCountResult(),
- Format(),
- "Completed"),
- Column(RawResult(),
- Format()),
- Column(MinResult(),
- Format()),
- Column(MaxResult(),
- Format()),
- Column(AmeanResult(),
- Format()),
- Column(StdResult(),
- Format(), "StdDev"),
- Column(CoeffVarResult(),
- CoeffVarFormat(), "StdDev/Mean"),
- Column(GmeanRatioResult(),
- RatioFormat(), "GmeanSpeedup"),
- Column(PValueResult(),
- PValueFormat(), "p-value")
- ]
- if not perf:
- return self._GetTables(self.labels, self.benchmark_runs, columns)
- return self. _GetPerfTables(self.labels, columns)
-
- def GetSummaryTables(self, perf=False):
- columns = [Column(NonEmptyCountResult(),
- Format(),
- "Completed"),
- Column(AmeanResult(),
- Format()),
- Column(StdResult(),
- Format(), "StdDev"),
- Column(CoeffVarResult(),
- CoeffVarFormat(), "StdDev/Mean"),
- Column(GmeanRatioResult(),
- RatioFormat(), "GmeanSpeedup"),
- Column(GmeanRatioResult(),
- ColorBoxFormat(), " "),
- Column(PValueResult(),
- PValueFormat(), "p-value")
- ]
- if not perf:
- return self._GetTables(self.labels, self.benchmark_runs, columns)
- return self. _GetPerfTables(self.labels, columns)
-
- def _ParseColumn(self, columns, iteration):
- new_column = []
- for column in columns:
- if column.result.__class__.__name__ != "RawResult":
- #TODO(asharif): tabulator should support full table natively.
- new_column.append(column)
- else:
- for i in range(iteration):
- cc = Column(LiteralResult(i), Format(), str(i+1))
- new_column.append(cc)
- return new_column
-
- def _AreAllRunsEmpty(self, runs):
- for label in runs:
- for dictionary in label:
- if dictionary:
- return False
- return True
-
- def _GetTableHeader(self, benchmark):
- benchmark_info = ("Benchmark: {0}; Iterations: {1}"
- .format(benchmark.name, benchmark.iterations))
- cell = Cell()
- cell.string_value = benchmark_info
- cell.header = True
- return [[cell]]
-
- def _GetTables(self, labels, benchmark_runs, columns):
- tables = []
- ro = ResultOrganizer(benchmark_runs, labels, self.benchmarks)
- result = ro.result
- label_name = ro.labels
- for item in result:
- runs = result[item]
- for benchmark in self.benchmarks:
- if benchmark.name == item:
- break
- ben_table = self._GetTableHeader(benchmark)
-
- if self._AreAllRunsEmpty(runs):
- cell = Cell()
- cell.string_value = ("This benchmark contains no result."
- " Is the benchmark name valid?")
- cell_table = [[cell]]
- else:
- tg = TableGenerator(runs, label_name)
- table = tg.GetTable()
- parsed_columns = self._ParseColumn(columns, benchmark.iterations)
- tf = TableFormatter(table, parsed_columns)
- cell_table = tf.GetCellTable()
- tables.append(ben_table)
- tables.append(cell_table)
- return tables
-
- def _GetPerfTables(self, labels, columns):
- tables = []
- label_names = [label.name for label in labels]
- p_table = PerfTable(self.experiment, label_names)
-
- if not p_table.perf_data:
- return tables
-
- for benchmark in p_table.perf_data:
- ben = None
- for ben in self.benchmarks:
- if ben.name == benchmark:
- break
-
- ben_table = self._GetTableHeader(ben)
- tables.append(ben_table)
- benchmark_data = p_table.perf_data[benchmark]
- row_info = p_table.row_info[benchmark]
- table = []
- for event in benchmark_data:
- tg = TableGenerator(benchmark_data[event], label_names,
- sort=TableGenerator.SORT_BY_VALUES_DESC)
- table = tg.GetTable(max(self.PERF_ROWS, row_info[event]))
- parsed_columns = self._ParseColumn(columns, ben.iterations)
- tf = TableFormatter(table, parsed_columns)
- tf.GenerateCellTable()
- tf.AddColumnName()
- tf.AddLabelName()
- tf.AddHeader(str(event))
- table = tf.GetCellTable(headers=False)
- tables.append(table)
- return tables
-
- def PrintTables(self, tables, out_to):
- output = ""
- if not tables:
- return output
- for table in tables:
- if out_to == "HTML":
- tp = TablePrinter(table, TablePrinter.HTML)
- elif out_to == "PLAIN":
- tp = TablePrinter(table, TablePrinter.PLAIN)
- elif out_to == "CONSOLE":
- tp = TablePrinter(table, TablePrinter.CONSOLE)
- elif out_to == "TSV":
- tp = TablePrinter(table, TablePrinter.TSV)
- elif out_to == "EMAIL":
- tp = TablePrinter(table, TablePrinter.EMAIL)
- else:
- pass
- output += tp.Print()
- return output
-
-
-class TextResultsReport(ResultsReport):
- TEXT = """
-===========================================
-Results report for: '%s'
-===========================================
-
--------------------------------------------
-Summary
--------------------------------------------
-%s
-
-
-Number re-images: %s
-
--------------------------------------------
-Benchmark Run Status
--------------------------------------------
-%s
-
-
--------------------------------------------
-Perf Data
--------------------------------------------
-%s
-
-
-
-Experiment File
--------------------------------------------
-%s
-
-
-CPUInfo
--------------------------------------------
-%s
-===========================================
-"""
-
- def __init__(self, experiment, email=False):
- super(TextResultsReport, self).__init__(experiment)
- self.email = email
-
- def GetStatusTable(self):
- """Generate the status table by the tabulator."""
- table = [["", ""]]
- columns = [Column(LiteralResult(iteration=0), Format(), "Status"),
- Column(LiteralResult(iteration=1), Format(), "Failing Reason")]
-
- for benchmark_run in self.benchmark_runs:
- status = [benchmark_run.name, [benchmark_run.timeline.GetLastEvent(),
- benchmark_run.failure_reason]]
- table.append(status)
- tf = TableFormatter(table, columns)
- cell_table = tf.GetCellTable()
- return [cell_table]
-
- def GetReport(self):
- """Generate the report for email and console."""
- status_table = self.GetStatusTable()
- summary_table = self.GetSummaryTables()
- full_table = self.GetFullTables()
- perf_table = self.GetSummaryTables(perf=True)
- if not perf_table:
- perf_table = None
- if not self.email:
- return self.TEXT % (self.experiment.name,
- self.PrintTables(summary_table, "CONSOLE"),
- self.experiment.machine_manager.num_reimages,
- self.PrintTables(status_table, "CONSOLE"),
- self.PrintTables(perf_table, "CONSOLE"),
- self.experiment.experiment_file,
- self.experiment.machine_manager.GetAllCPUInfo(
- self.experiment.labels))
-
- return self.TEXT % (self.experiment.name,
- self.PrintTables(summary_table, "EMAIL"),
- self.experiment.machine_manager.num_reimages,
- self.PrintTables(status_table, "EMAIL"),
- self.PrintTables(perf_table, "EMAIL"),
- self.experiment.experiment_file,
- self.experiment.machine_manager.GetAllCPUInfo(
- self.experiment.labels))
-
-
-class HTMLResultsReport(ResultsReport):
-
- HTML = """
-<html>
- <head>
- <style type="text/css">
-
-body {
- font-family: "Lucida Sans Unicode", "Lucida Grande", Sans-Serif;
- font-size: 12px;
-}
-
-pre {
- margin: 10px;
- color: #039;
- font-size: 14px;
-}
-
-.chart {
- display: inline;
-}
-
-.hidden {
- visibility: hidden;
-}
-
-.results-section {
- border: 1px solid #b9c9fe;
- margin: 10px;
-}
-
-.results-section-title {
- background-color: #b9c9fe;
- color: #039;
- padding: 7px;
- font-size: 14px;
- width: 200px;
-}
-
-.results-section-content {
- margin: 10px;
- padding: 10px;
- overflow:auto;
-}
-
-#box-table-a {
- font-size: 12px;
- width: 480px;
- text-align: left;
- border-collapse: collapse;
-}
-
-#box-table-a th {
- padding: 6px;
- background: #b9c9fe;
- border-right: 1px solid #fff;
- border-bottom: 1px solid #fff;
- color: #039;
- text-align: center;
-}
-
-#box-table-a td {
- padding: 4px;
- background: #e8edff;
- border-bottom: 1px solid #fff;
- border-right: 1px solid #fff;
- color: #669;
- border-top: 1px solid transparent;
-}
-
-#box-table-a tr:hover td {
- background: #d0dafd;
- color: #339;
-}
-
- </style>
- <script type='text/javascript' src='https://www.google.com/jsapi'></script>
- <script type='text/javascript'>
- google.load('visualization', '1', {packages:['corechart']});
- google.setOnLoadCallback(init);
- function init() {
- switchTab('summary', 'html');
- %s
- switchTab('full', 'html');
- drawTable();
- }
- function drawTable() {
- %s
- }
- function switchTab(table, tab) {
- document.getElementById(table + '-html').style.display = 'none';
- document.getElementById(table + '-text').style.display = 'none';
- document.getElementById(table + '-tsv').style.display = 'none';
- document.getElementById(table + '-' + tab).style.display = 'block';
- }
- </script>
- </head>
-
- <body>
- <div class='results-section'>
- <div class='results-section-title'>Summary Table</div>
- <div class='results-section-content'>
- <div id='summary-html'>%s</div>
- <div id='summary-text'><pre>%s</pre></div>
- <div id='summary-tsv'><pre>%s</pre></div>
- </div>
- %s
- </div>
- %s
- <div class='results-section'>
- <div class='results-section-title'>Charts</div>
- <div class='results-section-content'>%s</div>
- </div>
- <div class='results-section'>
- <div class='results-section-title'>Full Table</div>
- <div class='results-section-content'>
- <div id='full-html'>%s</div>
- <div id='full-text'><pre>%s</pre></div>
- <div id='full-tsv'><pre>%s</pre></div>
- </div>
- %s
- </div>
- <div class='results-section'>
- <div class='results-section-title'>Experiment File</div>
- <div class='results-section-content'>
- <pre>%s</pre>
- </div>
- </div>
- </body>
-</html>
-"""
-
- PERF_HTML = """
- <div class='results-section'>
- <div class='results-section-title'>Perf Table</div>
- <div class='results-section-content'>
- <div id='perf-html'>%s</div>
- <div id='perf-text'><pre>%s</pre></div>
- <div id='perf-tsv'><pre>%s</pre></div>
- </div>
- %s
- </div>
-"""
-
- def __init__(self, experiment):
- super(HTMLResultsReport, self).__init__(experiment)
-
- def _GetTabMenuHTML(self, table):
- return """
-<div class='tab-menu'>
- <a href="javascript:switchTab('%s', 'html')">HTML</a>
- <a href="javascript:switchTab('%s', 'text')">Text</a>
- <a href="javascript:switchTab('%s', 'tsv')">TSV</a>
-</div>""" % (table, table, table)
-
- def GetReport(self):
- chart_javascript = ""
- charts = self._GetCharts(self.labels, self.benchmark_runs)
- for chart in charts:
- chart_javascript += chart.GetJavascript()
- chart_divs = ""
- for chart in charts:
- chart_divs += chart.GetDiv()
-
- summary_table = self.GetSummaryTables()
- full_table = self.GetFullTables()
- perf_table = self.GetSummaryTables(perf=True)
- if perf_table:
- perf_html = self.PERF_HTML % (
- self.PrintTables(perf_table, "HTML"),
- self.PrintTables(perf_table, "PLAIN"),
- self.PrintTables(perf_table, "TSV"),
- self._GetTabMenuHTML("perf")
- )
- perf_init = "switchTab('perf', 'html');"
- else:
- perf_html = ""
- perf_init = ""
-
- return self.HTML % (perf_init,
- chart_javascript,
- self.PrintTables(summary_table, "HTML"),
- self.PrintTables(summary_table, "PLAIN"),
- self.PrintTables(summary_table, "TSV"),
- self._GetTabMenuHTML("summary"),
- perf_html,
- chart_divs,
- self.PrintTables(full_table, "HTML"),
- self.PrintTables(full_table, "PLAIN"),
- self.PrintTables(full_table, "TSV"),
- self._GetTabMenuHTML("full"),
- self.experiment.experiment_file)
-
- def _GetCharts(self, labels, benchmark_runs):
- charts = []
- ro = ResultOrganizer(benchmark_runs, labels)
- result = ro.result
- for item in result:
- runs = result[item]
- tg = TableGenerator(runs, ro.labels)
- table = tg.GetTable()
- columns = [Column(AmeanResult(),
- Format()),
- Column(MinResult(),
- Format()),
- Column(MaxResult(),
- Format())
- ]
- tf = TableFormatter(table, columns)
- data_table = tf.GetCellTable()
-
- for i in range(2, len(data_table)):
- cur_row_data = data_table[i]
- autotest_key = cur_row_data[0].string_value
- title = "{0}: {1}".format(item, autotest_key.replace("/", ""))
- chart = ColumnChart(title, 300, 200)
- chart.AddColumn("Label", "string")
- chart.AddColumn("Average", "number")
- chart.AddColumn("Min", "number")
- chart.AddColumn("Max", "number")
- chart.AddSeries("Min", "line", "black")
- chart.AddSeries("Max", "line", "black")
- cur_index = 1
- for label in ro.labels:
- chart.AddRow([label, cur_row_data[cur_index].value,
- cur_row_data[cur_index + 1].value,
- cur_row_data[cur_index + 2].value])
- if isinstance(cur_row_data[cur_index].value, str):
- chart = None
- break
- cur_index += 3
- if chart:
- charts.append(chart)
- return charts
diff --git a/v14/crosperf/results_sorter.py b/v14/crosperf/results_sorter.py
deleted file mode 100644
index 985a91fb..00000000
--- a/v14/crosperf/results_sorter.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-
-class ResultSorter(object):
- def __init__(self, benchmark_runs):
- self.table = {}
- for benchmark_run in benchmark_runs:
- benchmark_name = benchmark_run.benchmark_name
- label_name = benchmark_run.label_name
- if not benchmark_run.result:
- continue
- for autotest_key in benchmark_run.result.keyvals:
- result_tuple = (benchmark_name, autotest_key, label_name)
- if result_tuple not in self.table:
- self.table[result_tuple] = []
-
- cell = self.table[result_tuple]
- index = benchmark_run.iteration - 1
- while index >= len(cell):
- cell.append(None)
-
- result_value = benchmark_run.result.keyvals[autotest_key]
- try:
- result_value = float(result_value)
- except ValueError:
- pass
-
- cell[index] = result_value
-
- self.autotest_keys = {}
- for benchmark_run in benchmark_runs:
- benchmark_name = benchmark_run.benchmark_name
- if benchmark_name not in self.autotest_keys:
- self.autotest_keys[benchmark_name] = {}
- if not benchmark_run.result:
- continue
- for autotest_key in benchmark_run.result.keyvals:
- self.autotest_keys[benchmark_name][autotest_key] = True
-
- def GetAutotestKeys(self, benchmark_name):
- return self.autotest_keys[benchmark_name].keys()
-
- def GetResults(self, benchmark_name, autotest_key, label_name):
- try:
- return self.table[(benchmark_name, autotest_key, label_name)]
- except KeyError:
- return []
diff --git a/v14/crosperf/run_tests.sh b/v14/crosperf/run_tests.sh
deleted file mode 100755
index 2a35cc73..00000000
--- a/v14/crosperf/run_tests.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2011 Google Inc. All Rights Reserved.
-# Author: raymes@google.com (Raymes Khoury)
-
-export PYTHONPATH+=":.."
-for test in $(find -name \*test.py); do
- echo RUNNING: ${test}
- if ! ./${test} ; then
- echo "Test Failed!"
- exit 1
- fi
-done
diff --git a/v14/crosperf/settings.py b/v14/crosperf/settings.py
deleted file mode 100644
index e407a143..00000000
--- a/v14/crosperf/settings.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-
-class Settings(object):
- """Class representing settings (a set of fields) from an experiment file."""
-
- def __init__(self, name, settings_type):
- self.name = name
- self.settings_type = settings_type
- self.fields = {}
- self.parent = None
-
- def SetParentSettings(self, settings):
- """Set the parent settings which these settings can inherit from."""
- self.parent = settings
-
- def AddField(self, field):
- name = field.name
- if name in self.fields:
- raise Exception("Field %s defined previously." % name)
- self.fields[name] = field
-
- def SetField(self, name, value, append=False):
- if name not in self.fields:
- raise Exception("'%s' is not a valid field in '%s' settings"
- % (name, self.settings_type))
- if append:
- self.fields[name].Append(value)
- else:
- self.fields[name].Set(value)
-
- def GetField(self, name):
- """Get the value of a field with a given name."""
- if name not in self.fields:
- raise Exception("Field '%s' not a valid field in '%s' settings." %
- (name, self.name))
- field = self.fields[name]
- if not field.assigned and field.required:
- raise Exception("Required field '%s' not defined in '%s' settings." %
- (name, self.name))
- return self.fields[name].Get()
-
- def Inherit(self):
- """Inherit any unset values from the parent settings."""
- for name in self.fields:
- if (not self.fields[name].assigned and self.parent and
- name in self.parent.fields and self.parent.fields[name].assigned):
- self.fields[name].Set(self.parent.GetField(name), parse=False)
-
- def Override(self, settings):
- """Override settings with settings from a different object."""
- for name in settings.fields:
- if name in self.fields and settings.fields[name].assigned:
- self.fields[name].Set(settings.GetField(name), parse=False)
-
- def Validate(self):
- """Check that all required fields have been set."""
- for name in self.fields:
- if not self.fields[name].assigned and self.fields[name].required:
- raise Exception("Field %s is invalid." % name)
diff --git a/v14/crosperf/settings_factory.py b/v14/crosperf/settings_factory.py
deleted file mode 100644
index 924bc114..00000000
--- a/v14/crosperf/settings_factory.py
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-"""Setting files for global, benchmark and labels."""
-
-from field import BooleanField
-from field import FloatField
-from field import IntegerField
-from field import ListField
-from field import TextField
-from settings import Settings
-
-
-class BenchmarkSettings(Settings):
- def __init__(self, name):
- super(BenchmarkSettings, self).__init__(name, "benchmark")
- self.AddField(TextField("autotest_name",
- description="The name of the autotest to run."
- "Defaults to the name of the benchmark."))
- self.AddField(TextField("autotest_args",
- description="Arguments to be passed to the "
- "autotest."))
- self.AddField(IntegerField("iterations", default=1,
- description="Number of iterations to run the "
- "autotest."))
- self.AddField(FloatField("outlier_range", default=0.2,
- description="The percentage of highest/lowest "
- "values to omit when computing the average."))
- self.AddField(BooleanField("rm_chroot_tmp", default=False,
- description="Whether remove the run_remote_test"
- "result in the chroot"))
- self.AddField(BooleanField("key_results_only", default=True,
- description="Whether only show the key results"
- "of pyautoperf"))
- self.AddField(TextField("perf_args", default="",
- description="The optional profile command. It "
- "enables perf commands to record perforamance "
- "related counters. It must start with perf "
- "command record or stat followed by arguments."))
-
-
-class LabelSettings(Settings):
- def __init__(self, name):
- super(LabelSettings, self).__init__(name, "label")
- self.AddField(TextField("chromeos_image", required=True,
- description="The path to the image to run tests "
- "on."))
- self.AddField(TextField("chromeos_root",
- description="The path to a chromeos checkout which "
- "contains a src/scripts directory. Defaults to "
- "the chromeos checkout which contains the "
- "chromeos_image."))
- self.AddField(TextField("md5sum", default="",
- description="The md5sum of this image"))
- self.AddField(TextField("board", required=True, description="The target "
- "board for running experiments on, e.g. x86-alex."))
- self.AddField(ListField("remote", description=
- "A comma-separated list of ip's of chromeos"
- "devices to run experiments on."))
- self.AddField(TextField("image_args", required=False,
- default="",
- description="Extra arguments to pass to "
- "image_chromeos.py."))
- self.AddField(TextField("cache_dir", default="",
- description="The cache dir for this image."))
-
-
-class GlobalSettings(Settings):
- def __init__(self, name):
- super(GlobalSettings, self).__init__(name, "global")
- self.AddField(TextField("name",
- description="The name of the experiment. Just an "
- "identifier."))
- self.AddField(TextField("board", description="The target "
- "board for running experiments on, e.g. x86-alex."))
- self.AddField(ListField("remote",
- description="A comma-separated list of ip's of "
- "chromeos devices to run experiments on."))
- self.AddField(BooleanField("rerun_if_failed", description="Whether to "
- "re-run failed autotest runs or not.",
- default=False))
- self.AddField(BooleanField("rm_chroot_tmp", default=False,
- description="Whether remove the run_remote_test"
- "result in the chroot"))
- self.AddField(ListField("email", description="Space-seperated"
- "list of email addresses to send email to."))
- self.AddField(BooleanField("rerun", description="Whether to ignore the "
- "cache and for autotests to be re-run.",
- default=False))
- self.AddField(BooleanField("same_specs", default=True,
- description="Ensure cached runs are run on the "
- "same kind of devices which are specified as a "
- "remote."))
- self.AddField(BooleanField("same_machine", default=False,
- description="Ensure cached runs are run on the "
- "exact the same remote"))
- self.AddField(IntegerField("iterations", default=1,
- description="Number of iterations to run all "
- "autotests."))
- self.AddField(TextField("chromeos_root",
- description="The path to a chromeos checkout which "
- "contains a src/scripts directory. Defaults to "
- "the chromeos checkout which contains the "
- "chromeos_image."))
- self.AddField(BooleanField("key_results_only", default=True,
- description="Whether only show the key results"
- "of pyautoperf"))
- self.AddField(IntegerField("acquire_timeout", default=0,
- description="Number of seconds to wait for "
- "machine before exit if all the machines in "
- "the experiment file are busy. Default is 0"))
- self.AddField(TextField("perf_args", default="",
- description="The optional profile command. It "
- "enables perf commands to record perforamance "
- "related counters. It must start with perf "
- "command record or stat followed by arguments."))
- self.AddField(TextField("cache_dir", default="",
- description="The abs path of cache dir. "
- "Default is /home/$(whoami)/cros_scratch."))
- self.AddField(BooleanField("no_email", default=False,
- description="Whether to disable the email to "
- "user after crosperf finishes."))
- self.AddField(TextField("share_users", default="",
- description="Who's cache data you want to "
- "use. It accepts multiple users seperated by \",\""))
-
-
-class SettingsFactory(object):
- """Factory class for building different types of Settings objects.
-
- This factory is currently hardcoded to produce settings for ChromeOS
- experiment files. The idea is that in the future, other types
- of settings could be produced.
- """
-
- def GetSettings(self, name, settings_type):
- if settings_type == "label" or not settings_type:
- return LabelSettings(name)
- if settings_type == "global":
- return GlobalSettings(name)
- if settings_type == "benchmark":
- return BenchmarkSettings(name)
-
- raise Exception("Invalid settings type: '%s'." % settings_type)
diff --git a/v14/crosperf/test_flag.py b/v14/crosperf/test_flag.py
deleted file mode 100644
index 613138b2..00000000
--- a/v14/crosperf/test_flag.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-"""A global variable for testing."""
-
-
-_is_test = [False]
-
-
-def SetTestMode(flag):
- _is_test[0] = flag
-
-
-def GetTestMode():
- return _is_test[0]
diff --git a/v14/image_chromeos.py b/v14/image_chromeos.py
deleted file mode 100755
index d5d5f7fe..00000000
--- a/v14/image_chromeos.py
+++ /dev/null
@@ -1,320 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-"""Script to image a ChromeOS device.
-
-This script images a remote ChromeOS device with a specific image."
-"""
-
-__author__ = "asharif@google.com (Ahmad Sharif)"
-
-import filecmp
-import glob
-import optparse
-import os
-import re
-import shutil
-import sys
-import tempfile
-import time
-
-from utils import command_executer
-from utils import logger
-from utils import misc
-from utils.file_utils import FileUtils
-
-checksum_file = "/usr/local/osimage_checksum_file"
-lock_file = "/tmp/image_chromeos_lock/image_chromeos_lock"
-
-def Usage(parser, message):
- print "ERROR: " + message
- parser.print_help()
- sys.exit(0)
-
-
-def DoImage(argv):
- """Build ChromeOS."""
-
- # Common initializations
- cmd_executer = command_executer.GetCommandExecuter()
- l = logger.GetLogger()
-
- parser = optparse.OptionParser()
- parser.add_option("-c", "--chromeos_root", dest="chromeos_root",
- help="Target directory for ChromeOS installation.")
- parser.add_option("-r", "--remote", dest="remote",
- help="Target device.")
- parser.add_option("-i", "--image", dest="image",
- help="Image binary file.")
- parser.add_option("-b", "--board", dest="board",
- help="Target board override.")
- parser.add_option("-f", "--force", dest="force",
- action="store_true",
- default=False,
- help="Force an image even if it is non-test.")
- parser.add_option("-a",
- "--image_args",
- dest="image_args")
-
-
- options = parser.parse_args(argv[1:])[0]
-
- if options.chromeos_root is None:
- Usage(parser, "--chromeos_root must be set")
-
- if options.remote is None:
- Usage(parser, "--remote must be set")
-
- options.chromeos_root = os.path.expanduser(options.chromeos_root)
-
- if options.board is None:
- board = cmd_executer.CrosLearnBoard(options.chromeos_root, options.remote)
- else:
- board = options.board
-
- if options.image is None:
- images_dir = misc.GetImageDir(options.chromeos_root, board)
- image = os.path.join(images_dir,
- "latest",
- "chromiumos_test_image.bin")
- if not os.path.exists(image):
- image = os.path.join(images_dir,
- "latest",
- "chromiumos_image.bin")
- else:
- image = options.image
- image = os.path.expanduser(image)
-
- image = os.path.realpath(image)
-
- if not os.path.exists(image):
- Usage(parser, "Image file: " + image + " does not exist!")
-
- image_checksum = FileUtils().Md5File(image)
-
- command = "cat " + checksum_file
- retval, device_checksum, err = cmd_executer.CrosRunCommand(command,
- return_output=True,
- chromeos_root=options.chromeos_root,
- machine=options.remote)
-
- device_checksum = device_checksum.strip()
- image_checksum = str(image_checksum)
-
- l.LogOutput("Image checksum: " + image_checksum)
- l.LogOutput("Device checksum: " + device_checksum)
-
- if image_checksum != device_checksum:
- [found, located_image] = LocateOrCopyImage(options.chromeos_root,
- image,
- board=board)
-
- l.LogOutput("Checksums do not match. Re-imaging...")
-
- is_test_image = IsImageModdedForTest(options.chromeos_root,
- located_image)
-
- if not is_test_image and not options.force:
- logger.GetLogger().LogFatal("Have to pass --force to image a non-test "
- "image!")
-
- # If the device has /tmp mounted as noexec, image_to_live.sh can fail.
- command = "mount -o remount,rw,exec /tmp"
- cmd_executer.CrosRunCommand(command,
- chromeos_root=options.chromeos_root,
- machine=options.remote)
-
- real_src_dir = os.path.join(os.path.realpath(options.chromeos_root),
- "src")
- if located_image.find(real_src_dir) != 0:
- raise Exception("Located image: %s not in chromeos_root: %s" %
- (located_image, options.chromeos_root))
- chroot_image = os.path.join(
- "..",
- located_image[len(real_src_dir):].lstrip("/"))
- cros_image_to_target_args = ["--remote=%s" % options.remote,
- "--board=%s" % board,
- "--from=%s" % os.path.dirname(chroot_image),
- "--image-name=%s" %
- os.path.basename(located_image)]
-
- command = ("./bin/cros_image_to_target.py %s" %
- " ".join(cros_image_to_target_args))
- if options.image_args:
- command += " %s" % options.image_args
-
- # Workaround for crosbug.com/35684.
- os.chmod(misc.GetChromeOSKeyFile(options.chromeos_root), 0600)
- retval = cmd_executer.ChrootRunCommand(options.chromeos_root,
- command)
- if found == False:
- temp_dir = os.path.dirname(located_image)
- l.LogOutput("Deleting temp image dir: %s" % temp_dir)
- shutil.rmtree(temp_dir)
-
- logger.GetLogger().LogFatalIf(retval, "Image command failed")
-
- # Unfortunately cros_image_to_target.py sometimes returns early when the
- # machine isn't fully up yet.
- retval = EnsureMachineUp(options.chromeos_root, options.remote)
-
- command = "echo %s > %s && chmod -w %s" % (image_checksum, checksum_file,
- checksum_file)
- retval = cmd_executer.CrosRunCommand(command,
- chromeos_root=options.chromeos_root,
- machine=options.remote)
- logger.GetLogger().LogFatalIf(retval, "Writing checksum failed.")
-
- successfully_imaged = VerifyChromeChecksum(options.chromeos_root,
- image,
- options.remote)
- logger.GetLogger().LogFatalIf(not successfully_imaged,
- "Image verification failed!")
- TryRemountPartitionAsRW(options.chromeos_root, options.remote)
- else:
- l.LogOutput("Checksums match. Skipping reimage")
- return retval
-
-
-def LocateOrCopyImage(chromeos_root, image, board=None):
- l = logger.GetLogger()
- if board is None:
- board_glob = "*"
- else:
- board_glob = board
-
- chromeos_root_realpath = os.path.realpath(chromeos_root)
- image = os.path.realpath(image)
-
- if image.startswith("%s/" % chromeos_root_realpath):
- return [True, image]
-
- # First search within the existing build dirs for any matching files.
- images_glob = ("%s/src/build/images/%s/*/*.bin" %
- (chromeos_root_realpath,
- board_glob))
- images_list = glob.glob(images_glob)
- for potential_image in images_list:
- if filecmp.cmp(potential_image, image):
- l.LogOutput("Found matching image %s in chromeos_root." % potential_image)
- return [True, potential_image]
- # We did not find an image. Copy it in the src dir and return the copied file.
- if board is None:
- board = ""
- base_dir = ("%s/src/build/images/%s" %
- (chromeos_root_realpath,
- board))
- if not os.path.isdir(base_dir):
- os.makedirs(base_dir)
- temp_dir = tempfile.mkdtemp(prefix="%s/tmp" % base_dir)
- new_image = "%s/%s" % (temp_dir, os.path.basename(image))
- l.LogOutput("No matching image found. Copying %s to %s" %
- (image, new_image))
- shutil.copyfile(image, new_image)
- return [False, new_image]
-
-
-def GetImageMountCommand(chromeos_root, image, rootfs_mp, stateful_mp):
- image_dir = os.path.dirname(image)
- image_file = os.path.basename(image)
- mount_command = ("cd %s/src/scripts &&"
- "./mount_gpt_image.sh --from=%s --image=%s"
- " --safe --read_only"
- " --rootfs_mountpt=%s"
- " --stateful_mountpt=%s" %
- (chromeos_root, image_dir, image_file, rootfs_mp,
- stateful_mp))
- return mount_command
-
-
-def MountImage(chromeos_root, image, rootfs_mp, stateful_mp, unmount=False):
- cmd_executer = command_executer.GetCommandExecuter()
- command = GetImageMountCommand(chromeos_root, image, rootfs_mp, stateful_mp)
- if unmount:
- command = "%s --unmount" % command
- retval = cmd_executer.RunCommand(command)
- logger.GetLogger().LogFatalIf(retval, "Mount/unmount command failed!")
- return retval
-
-
-def IsImageModdedForTest(chromeos_root, image):
- rootfs_mp = tempfile.mkdtemp()
- stateful_mp = tempfile.mkdtemp()
- MountImage(chromeos_root, image, rootfs_mp, stateful_mp)
- lsb_release_file = os.path.join(rootfs_mp, "etc/lsb-release")
- lsb_release_contents = open(lsb_release_file).read()
- is_test_image = re.search("test", lsb_release_contents, re.IGNORECASE)
- MountImage(chromeos_root, image, rootfs_mp, stateful_mp, unmount=True)
- return is_test_image
-
-
-def VerifyChromeChecksum(chromeos_root, image, remote):
- cmd_executer = command_executer.GetCommandExecuter()
- rootfs_mp = tempfile.mkdtemp()
- stateful_mp = tempfile.mkdtemp()
- MountImage(chromeos_root, image, rootfs_mp, stateful_mp)
- image_chrome_checksum = FileUtils().Md5File("%s/opt/google/chrome/chrome" %
- rootfs_mp)
- MountImage(chromeos_root, image, rootfs_mp, stateful_mp, unmount=True)
-
- command = "md5sum /opt/google/chrome/chrome"
- [r, o, e] = cmd_executer.CrosRunCommand(command,
- return_output=True,
- chromeos_root=chromeos_root,
- machine=remote)
- device_chrome_checksum = o.split()[0]
- if image_chrome_checksum.strip() == device_chrome_checksum.strip():
- return True
- else:
- return False
-
-# Remount partition as writable.
-# TODO: auto-detect if an image is built using --noenable_rootfs_verification.
-def TryRemountPartitionAsRW(chromeos_root, remote):
- l = logger.GetLogger()
- cmd_executer = command_executer.GetCommandExecuter()
- command = "sudo mount -o remount,rw /"
- retval = cmd_executer.CrosRunCommand(\
- command, chromeos_root=chromeos_root, machine=remote, terminated_timeout=10)
- if retval:
- ## Safely ignore.
- l.LogWarning("Failed to remount partition as rw, "
- "probably the image was not built with "
- "\"--noenable_rootfs_verification\", "
- "you can safely ignore this.")
- else:
- l.LogOutput("Re-mounted partition as writable.")
-
-
-def EnsureMachineUp(chromeos_root, remote):
- l = logger.GetLogger()
- cmd_executer = command_executer.GetCommandExecuter()
- timeout = 600
- magic = "abcdefghijklmnopqrstuvwxyz"
- command = "echo %s" % magic
- start_time = time.time()
- while True:
- current_time = time.time()
- if current_time - start_time > timeout:
- l.LogError("Timeout of %ss reached. Machine still not up. Aborting." %
- timeout)
- return False
- retval = cmd_executer.CrosRunCommand(command,
- chromeos_root=chromeos_root,
- machine=remote)
- if not retval:
- return True
-
-
-def Main(argv):
- misc.AcquireLock(lock_file)
- try:
- return DoImage(argv)
- finally:
- misc.ReleaseLock(lock_file)
-
-
-if __name__ == "__main__":
- retval = Main(sys.argv)
- sys.exit(retval)
diff --git a/v14/utils/__init__.py b/v14/utils/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/v14/utils/__init__.py
+++ /dev/null
diff --git a/v14/utils/colortrans.py b/v14/utils/colortrans.py
deleted file mode 100644
index 37e91572..00000000
--- a/v14/utils/colortrans.py
+++ /dev/null
@@ -1,376 +0,0 @@
-#! /usr/bin/env python
-
-""" Convert values between RGB hex codes and xterm-256 color codes.
-
-Nice long listing of all 256 colors and their codes. Useful for
-developing console color themes, or even script output schemes.
-
-Resources:
-* http://en.wikipedia.org/wiki/8-bit_color
-* http://en.wikipedia.org/wiki/ANSI_escape_code
-* /usr/share/X11/rgb.txt
-
-I'm not sure where this script was inspired from. I think I must have
-written it from scratch, though it's been several years now.
-"""
-
-__author__ = 'Micah Elliott http://MicahElliott.com'
-__version__ = '0.1'
-__copyright__ = 'Copyright (C) 2011 Micah Elliott. All rights reserved.'
-__license__ = 'WTFPL http://sam.zoy.org/wtfpl/'
-
-#---------------------------------------------------------------------
-
-import sys, re
-
-CLUT = [ # color look-up table
-# 8-bit, RGB hex
-
- # Primary 3-bit (8 colors). Unique representation!
- ('00', '000000'),
- ('01', '800000'),
- ('02', '008000'),
- ('03', '808000'),
- ('04', '000080'),
- ('05', '800080'),
- ('06', '008080'),
- ('07', 'c0c0c0'),
-
- # Equivalent "bright" versions of original 8 colors.
- ('08', '808080'),
- ('09', 'ff0000'),
- ('10', '00ff00'),
- ('11', 'ffff00'),
- ('12', '0000ff'),
- ('13', 'ff00ff'),
- ('14', '00ffff'),
- ('15', 'ffffff'),
-
- # Strictly ascending.
- ('16', '000000'),
- ('17', '00005f'),
- ('18', '000087'),
- ('19', '0000af'),
- ('20', '0000d7'),
- ('21', '0000ff'),
- ('22', '005f00'),
- ('23', '005f5f'),
- ('24', '005f87'),
- ('25', '005faf'),
- ('26', '005fd7'),
- ('27', '005fff'),
- ('28', '008700'),
- ('29', '00875f'),
- ('30', '008787'),
- ('31', '0087af'),
- ('32', '0087d7'),
- ('33', '0087ff'),
- ('34', '00af00'),
- ('35', '00af5f'),
- ('36', '00af87'),
- ('37', '00afaf'),
- ('38', '00afd7'),
- ('39', '00afff'),
- ('40', '00d700'),
- ('41', '00d75f'),
- ('42', '00d787'),
- ('43', '00d7af'),
- ('44', '00d7d7'),
- ('45', '00d7ff'),
- ('46', '00ff00'),
- ('47', '00ff5f'),
- ('48', '00ff87'),
- ('49', '00ffaf'),
- ('50', '00ffd7'),
- ('51', '00ffff'),
- ('52', '5f0000'),
- ('53', '5f005f'),
- ('54', '5f0087'),
- ('55', '5f00af'),
- ('56', '5f00d7'),
- ('57', '5f00ff'),
- ('58', '5f5f00'),
- ('59', '5f5f5f'),
- ('60', '5f5f87'),
- ('61', '5f5faf'),
- ('62', '5f5fd7'),
- ('63', '5f5fff'),
- ('64', '5f8700'),
- ('65', '5f875f'),
- ('66', '5f8787'),
- ('67', '5f87af'),
- ('68', '5f87d7'),
- ('69', '5f87ff'),
- ('70', '5faf00'),
- ('71', '5faf5f'),
- ('72', '5faf87'),
- ('73', '5fafaf'),
- ('74', '5fafd7'),
- ('75', '5fafff'),
- ('76', '5fd700'),
- ('77', '5fd75f'),
- ('78', '5fd787'),
- ('79', '5fd7af'),
- ('80', '5fd7d7'),
- ('81', '5fd7ff'),
- ('82', '5fff00'),
- ('83', '5fff5f'),
- ('84', '5fff87'),
- ('85', '5fffaf'),
- ('86', '5fffd7'),
- ('87', '5fffff'),
- ('88', '870000'),
- ('89', '87005f'),
- ('90', '870087'),
- ('91', '8700af'),
- ('92', '8700d7'),
- ('93', '8700ff'),
- ('94', '875f00'),
- ('95', '875f5f'),
- ('96', '875f87'),
- ('97', '875faf'),
- ('98', '875fd7'),
- ('99', '875fff'),
- ('100', '878700'),
- ('101', '87875f'),
- ('102', '878787'),
- ('103', '8787af'),
- ('104', '8787d7'),
- ('105', '8787ff'),
- ('106', '87af00'),
- ('107', '87af5f'),
- ('108', '87af87'),
- ('109', '87afaf'),
- ('110', '87afd7'),
- ('111', '87afff'),
- ('112', '87d700'),
- ('113', '87d75f'),
- ('114', '87d787'),
- ('115', '87d7af'),
- ('116', '87d7d7'),
- ('117', '87d7ff'),
- ('118', '87ff00'),
- ('119', '87ff5f'),
- ('120', '87ff87'),
- ('121', '87ffaf'),
- ('122', '87ffd7'),
- ('123', '87ffff'),
- ('124', 'af0000'),
- ('125', 'af005f'),
- ('126', 'af0087'),
- ('127', 'af00af'),
- ('128', 'af00d7'),
- ('129', 'af00ff'),
- ('130', 'af5f00'),
- ('131', 'af5f5f'),
- ('132', 'af5f87'),
- ('133', 'af5faf'),
- ('134', 'af5fd7'),
- ('135', 'af5fff'),
- ('136', 'af8700'),
- ('137', 'af875f'),
- ('138', 'af8787'),
- ('139', 'af87af'),
- ('140', 'af87d7'),
- ('141', 'af87ff'),
- ('142', 'afaf00'),
- ('143', 'afaf5f'),
- ('144', 'afaf87'),
- ('145', 'afafaf'),
- ('146', 'afafd7'),
- ('147', 'afafff'),
- ('148', 'afd700'),
- ('149', 'afd75f'),
- ('150', 'afd787'),
- ('151', 'afd7af'),
- ('152', 'afd7d7'),
- ('153', 'afd7ff'),
- ('154', 'afff00'),
- ('155', 'afff5f'),
- ('156', 'afff87'),
- ('157', 'afffaf'),
- ('158', 'afffd7'),
- ('159', 'afffff'),
- ('160', 'd70000'),
- ('161', 'd7005f'),
- ('162', 'd70087'),
- ('163', 'd700af'),
- ('164', 'd700d7'),
- ('165', 'd700ff'),
- ('166', 'd75f00'),
- ('167', 'd75f5f'),
- ('168', 'd75f87'),
- ('169', 'd75faf'),
- ('170', 'd75fd7'),
- ('171', 'd75fff'),
- ('172', 'd78700'),
- ('173', 'd7875f'),
- ('174', 'd78787'),
- ('175', 'd787af'),
- ('176', 'd787d7'),
- ('177', 'd787ff'),
- ('178', 'd7af00'),
- ('179', 'd7af5f'),
- ('180', 'd7af87'),
- ('181', 'd7afaf'),
- ('182', 'd7afd7'),
- ('183', 'd7afff'),
- ('184', 'd7d700'),
- ('185', 'd7d75f'),
- ('186', 'd7d787'),
- ('187', 'd7d7af'),
- ('188', 'd7d7d7'),
- ('189', 'd7d7ff'),
- ('190', 'd7ff00'),
- ('191', 'd7ff5f'),
- ('192', 'd7ff87'),
- ('193', 'd7ffaf'),
- ('194', 'd7ffd7'),
- ('195', 'd7ffff'),
- ('196', 'ff0000'),
- ('197', 'ff005f'),
- ('198', 'ff0087'),
- ('199', 'ff00af'),
- ('200', 'ff00d7'),
- ('201', 'ff00ff'),
- ('202', 'ff5f00'),
- ('203', 'ff5f5f'),
- ('204', 'ff5f87'),
- ('205', 'ff5faf'),
- ('206', 'ff5fd7'),
- ('207', 'ff5fff'),
- ('208', 'ff8700'),
- ('209', 'ff875f'),
- ('210', 'ff8787'),
- ('211', 'ff87af'),
- ('212', 'ff87d7'),
- ('213', 'ff87ff'),
- ('214', 'ffaf00'),
- ('215', 'ffaf5f'),
- ('216', 'ffaf87'),
- ('217', 'ffafaf'),
- ('218', 'ffafd7'),
- ('219', 'ffafff'),
- ('220', 'ffd700'),
- ('221', 'ffd75f'),
- ('222', 'ffd787'),
- ('223', 'ffd7af'),
- ('224', 'ffd7d7'),
- ('225', 'ffd7ff'),
- ('226', 'ffff00'),
- ('227', 'ffff5f'),
- ('228', 'ffff87'),
- ('229', 'ffffaf'),
- ('230', 'ffffd7'),
- ('231', 'ffffff'),
-
- # Gray-scale range.
- ('232', '080808'),
- ('233', '121212'),
- ('234', '1c1c1c'),
- ('235', '262626'),
- ('236', '303030'),
- ('237', '3a3a3a'),
- ('238', '444444'),
- ('239', '4e4e4e'),
- ('240', '585858'),
- ('241', '626262'),
- ('242', '6c6c6c'),
- ('243', '767676'),
- ('244', '808080'),
- ('245', '8a8a8a'),
- ('246', '949494'),
- ('247', '9e9e9e'),
- ('248', 'a8a8a8'),
- ('249', 'b2b2b2'),
- ('250', 'bcbcbc'),
- ('251', 'c6c6c6'),
- ('252', 'd0d0d0'),
- ('253', 'dadada'),
- ('254', 'e4e4e4'),
- ('255', 'eeeeee'),
-]
-
-def _str2hex(hexstr):
- return int(hexstr, 16)
-
-def _strip_hash(rgb):
- # Strip leading `#` if exists.
- if rgb.startswith('#'):
- rgb = rgb.lstrip('#')
- return rgb
-
-def _create_dicts():
- short2rgb_dict = dict(CLUT)
- rgb2short_dict = {}
- for k, v in short2rgb_dict.items():
- rgb2short_dict[v] = k
- return rgb2short_dict, short2rgb_dict
-
-def short2rgb(short):
- return SHORT2RGB_DICT[short]
-
-def print_all():
- """ Print all 256 xterm color codes.
- """
- for short, rgb in CLUT:
- sys.stdout.write('\033[48;5;%sm%s:%s' % (short, short, rgb))
- sys.stdout.write("\033[0m ")
- sys.stdout.write('\033[38;5;%sm%s:%s' % (short, short, rgb))
- sys.stdout.write("\033[0m\n")
- print "Printed all codes."
- print "You can translate a hex or 0-255 code by providing an argument."
-
-def rgb2short(rgb):
- """ Find the closest xterm-256 approximation to the given RGB value.
- @param rgb: Hex code representing an RGB value, eg, 'abcdef'
- @returns: String between 0 and 255, compatible with xterm.
- >>> rgb2short('123456')
- ('23', '005f5f')
- >>> rgb2short('ffffff')
- ('231', 'ffffff')
- >>> rgb2short('0DADD6') # vimeo logo
- ('38', '00afd7')
- """
- rgb = _strip_hash(rgb)
- incs = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff)
- # Break 6-char RGB code into 3 integer vals.
- parts = [ int(h, 16) for h in re.split(r'(..)(..)(..)', rgb)[1:4] ]
- res = []
- for part in parts:
- i = 0
- while i < len(incs)-1:
- s, b = incs[i], incs[i+1] # smaller, bigger
- if s <= part <= b:
- s1 = abs(s - part)
- b1 = abs(b - part)
- if s1 < b1: closest = s
- else: closest = b
- res.append(closest)
- break
- i += 1
- #print '***', res
- res = ''.join([ ('%02.x' % i) for i in res ])
- equiv = RGB2SHORT_DICT[ res ]
- #print '***', res, equiv
- return equiv, res
-
-RGB2SHORT_DICT, SHORT2RGB_DICT = _create_dicts()
-
-#---------------------------------------------------------------------
-
-if __name__ == '__main__':
- import doctest
- doctest.testmod()
- if len(sys.argv) == 1:
- print_all()
- raise SystemExit
- arg = sys.argv[1]
- if len(arg) < 4 and int(arg) < 256:
- rgb = short2rgb(arg)
- sys.stdout.write('xterm color \033[38;5;%sm%s\033[0m -> RGB exact \033[38;5;%sm%s\033[0m' % (arg, arg, arg, rgb))
- sys.stdout.write("\033[0m\n")
- else:
- short, rgb = rgb2short(arg)
- sys.stdout.write('RGB %s -> xterm color approx \033[38;5;%sm%s (%s)' % (arg, short, short, rgb))
- sys.stdout.write("\033[0m\n")
diff --git a/v14/utils/command_executer.py b/v14/utils/command_executer.py
deleted file mode 100644
index 0aedc47c..00000000
--- a/v14/utils/command_executer.py
+++ /dev/null
@@ -1,338 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2011 Google Inc. All Rights Reserved.
-#
-
-import getpass
-import os
-import pty
-import re
-import select
-import subprocess
-import tempfile
-import time
-
-import logger
-import misc
-
-mock_default = False
-
-
-def InitCommandExecuter(mock=False):
- global mock_default
- # Whether to default to a mock command executer or not
- mock_default = mock
-
-
-def GetCommandExecuter(logger_to_set=None, mock=False):
- # If the default is a mock executer, always return one.
- if mock_default or mock:
- return MockCommandExecuter(logger_to_set)
- else:
- return CommandExecuter(logger_to_set)
-
-
-class CommandExecuter:
- def __init__(self, logger_to_set=None):
- if logger_to_set is not None:
- self.logger = logger_to_set
- else:
- self.logger = logger.GetLogger()
-
- def RunCommand(self, cmd, return_output=False, machine=None,
- username=None, command_terminator=None,
- command_timeout=None,
- terminated_timeout=10,
- print_to_console=True):
- """Run a command."""
-
- cmd = str(cmd)
-
- self.logger.LogCmd(cmd, machine, username, print_to_console)
- if command_terminator and command_terminator.IsTerminated():
- self.logger.LogError("Command was terminated!", print_to_console)
- if return_output:
- return [1, "", ""]
- else:
- return 1
-
- if machine is not None:
- user = ""
- if username is not None:
- user = username + "@"
- cmd = "ssh -t -t %s%s -- '%s'" % (user, machine, cmd)
-
- pty_fds = pty.openpty()
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- stdin=pty_fds[0], shell=True)
-
- full_stdout = ""
- full_stderr = ""
-
- # Pull output from pipes, send it to file/stdout/string
- out = err = None
- pipes = [p.stdout, p.stderr]
-
- my_poll = select.poll()
- my_poll.register(p.stdout, select.POLLIN)
- my_poll.register(p.stderr, select.POLLIN)
-
- terminated_time = None
- started_time = time.time()
-
- while len(pipes):
- if command_terminator and command_terminator.IsTerminated():
- self.RunCommand("sudo kill -9 " + str(p.pid),
- print_to_console=print_to_console)
- wait = p.wait()
- self.logger.LogError("Command was terminated!", print_to_console)
- if return_output:
- return (p.wait, full_stdout, full_stderr)
- else:
- return wait
-
- l=my_poll.poll(100)
- for (fd, evt) in l:
- if fd == p.stdout.fileno():
- out = os.read(p.stdout.fileno(), 16384)
- if return_output:
- full_stdout += out
- self.logger.LogCommandOutput(out, print_to_console)
- if out == "":
- pipes.remove(p.stdout)
- my_poll.unregister(p.stdout)
- if fd == p.stderr.fileno():
- err = os.read(p.stderr.fileno(), 16384)
- if return_output:
- full_stderr += err
- self.logger.LogCommandError(err, print_to_console)
- if err == "":
- pipes.remove(p.stderr)
- my_poll.unregister(p.stderr)
-
- if p.poll() is not None:
- if terminated_time is None:
- terminated_time = time.time()
- elif (terminated_timeout is not None and
- time.time() - terminated_time > terminated_timeout):
- m = ("Timeout of %s seconds reached since process termination."
- % terminated_timeout)
- self.logger.LogWarning(m, print_to_console)
- break
-
- if (command_timeout is not None and
- time.time() - started_time > command_timeout):
- m = ("Timeout of %s seconds reached since process started."
- % command_timeout)
- self.logger.LogWarning(m, print_to_console)
- self.RunCommand("kill %d || sudo kill %d || sudo kill -9 %d" %
- (p.pid, p.pid, p.pid),
- print_to_console=print_to_console)
- break
-
- if out == err == "":
- break
-
- p.wait()
- os.close(pty_fds[0])
- os.close(pty_fds[1])
- if return_output:
- return (p.returncode, full_stdout, full_stderr)
- return p.returncode
-
- def RemoteAccessInitCommand(self, chromeos_root, machine):
- command = ""
- command += "\nset -- --remote=" + machine
- command += "\n. " + chromeos_root + "/src/scripts/common.sh"
- command += "\n. " + chromeos_root + "/src/scripts/remote_access.sh"
- command += "\nTMP=$(mktemp -d)"
- command += "\nFLAGS \"$@\" || exit 1"
- command += "\nremote_access_init"
- return command
-
- def WriteToTempShFile(self, contents):
- handle, command_file = tempfile.mkstemp(prefix=os.uname()[1],
- suffix=".sh")
- os.write(handle, "#!/bin/bash\n")
- os.write(handle, contents)
- os.close(handle)
- return command_file
-
-
- def CrosLearnBoard(self, chromeos_root, machine):
- command = self.RemoteAccessInitCommand(chromeos_root, machine)
- command += "\nlearn_board"
- command += "\necho ${FLAGS_board}"
- retval, output, err = self.RunCommand(command, True)
- self.logger.LogFatalIf(retval, "learn_board command failed")
- return output.split()[-1]
-
- def CrosRunCommand(self, cmd, return_output=False, machine=None,
- username=None, command_terminator=None, chromeos_root=None,
- command_timeout=None,
- terminated_timeout=10,
- print_to_console=True):
- """Run a command on a chromeos box"""
- self.logger.LogCmd(cmd, print_to_console)
- self.logger.LogFatalIf(not machine, "No machine provided!")
- self.logger.LogFatalIf(not chromeos_root, "chromeos_root not given!")
- chromeos_root = os.path.expanduser(chromeos_root)
-
- # Write all commands to a file.
- command_file = self.WriteToTempShFile(cmd)
- retval = self.CopyFiles(command_file, command_file,
- dest_machine=machine,
- command_terminator=command_terminator,
- chromeos_root=chromeos_root,
- dest_cros=True,
- recursive=False,
- print_to_console=print_to_console)
- if retval:
- self.logger.LogError("Could not run remote command on machine."
- " Is the machine up?")
- return retval
-
- command = self.RemoteAccessInitCommand(chromeos_root, machine)
- command += "\nremote_sh bash %s" % command_file
- command += "\necho \"$REMOTE_OUT\""
- retval = self.RunCommand(command, return_output,
- command_terminator=command_terminator,
- command_timeout=command_timeout,
- terminated_timeout=terminated_timeout,
- print_to_console=print_to_console)
- if return_output:
- connect_signature = ("Initiating first contact with remote host\n" +
- "Connection OK\n")
- connect_signature_re = re.compile(connect_signature)
- modded_return = []
- for r in retval:
- modded_return.append(r)
- modded_return[1] = connect_signature_re.sub("", modded_return[1])
- return modded_return
- return retval
-
- def ChrootRunCommand(self, chromeos_root, command, return_output=False,
- command_terminator=None, command_timeout=None,
- terminated_timeout=10,
- print_to_console=True,
- cros_sdk_options=""):
- self.logger.LogCmd(command, print_to_console)
-
- handle, command_file = tempfile.mkstemp(dir=os.path.join(chromeos_root,
- "src/scripts"),
- suffix=".sh",
- prefix="in_chroot_cmd")
- os.write(handle, "#!/bin/bash\n")
- os.write(handle, command)
- os.close(handle)
-
- os.chmod(command_file, 0777)
-
- command = "cd %s; cros_sdk %s -- ./%s" % (chromeos_root, cros_sdk_options,
- os.path.basename(command_file))
- ret = self.RunCommand(command, return_output,
- command_terminator=command_terminator,
- command_timeout=command_timeout,
- terminated_timeout=terminated_timeout,
- print_to_console=print_to_console)
- os.remove(command_file)
- return ret
-
-
- def RunCommands(self, cmdlist, return_output=False, machine=None,
- username=None, command_terminator=None):
- cmd = " ;\n" .join(cmdlist)
- return self.RunCommand(cmd, return_output, machine, username,
- command_terminator)
-
- def CopyFiles(self, src, dest, src_machine=None, dest_machine=None,
- src_user=None, dest_user=None, recursive=True,
- command_terminator=None,
- chromeos_root=None, src_cros=False, dest_cros=False,
- print_to_console=True):
- src = os.path.expanduser(src)
- dest = os.path.expanduser(dest)
-
- if recursive:
- src = src + "/"
- dest = dest + "/"
-
- if src_cros == True or dest_cros == True:
- self.logger.LogFatalIf(not (src_cros ^ dest_cros), "Only one of src_cros "
- "and desc_cros can be non-null.")
- self.logger.LogFatalIf(not chromeos_root, "chromeos_root not given!")
- if src_cros == True:
- cros_machine = src_machine
- else:
- cros_machine = dest_machine
-
- command = self.RemoteAccessInitCommand(chromeos_root, cros_machine)
- src_parent, src_child = misc.GetRoot(src)
- dest_parent, dest_child = misc.GetRoot(dest)
- ssh_command = ("ssh -p ${FLAGS_ssh_port}" +
- " -o StrictHostKeyChecking=no" +
- " -o UserKnownHostsFile=$(mktemp)" +
- " -i $TMP_PRIVATE_KEY")
- rsync_prefix = "\nrsync -r -e \"%s\" " % ssh_command
- if dest_cros == True:
- command += rsync_prefix + "%s root@%s:%s" % (src, dest_machine, dest)
- return self.RunCommand(command,
- machine=src_machine,
- username=src_user,
- command_terminator=command_terminator,
- print_to_console=print_to_console)
- else:
- command += rsync_prefix + "root@%s:%s %s" % (src_machine, src, dest)
- return self.RunCommand(command,
- machine=dest_machine,
- username=dest_user,
- command_terminator=command_terminator,
- print_to_console=print_to_console)
-
-
- if dest_machine == src_machine:
- command = ("rsync -a %s %s" %
- (src,
- dest))
- else:
- if src_machine is None:
- src_machine = os.uname()[1]
- src_user = getpass.getuser()
- command = ("rsync -a %s@%s:%s %s" %
- (src_user, src_machine, src,
- dest))
- return self.RunCommand(command,
- machine=dest_machine,
- username=dest_user,
- command_terminator=command_terminator,
- print_to_console=print_to_console)
-
-
-class MockCommandExecuter(CommandExecuter):
- def __init__(self, logger_to_set=None):
- if logger is not None:
- self.logger = logger_to_set
- else:
- self.logger = logger.GetLogger()
-
- def RunCommand(self, cmd, return_output=False, machine=None, username=None,
- command_terminator=None):
- cmd = str(cmd)
- if machine is None:
- machine = "localhost"
- if username is None:
- username = "current"
- logger.GetLogger().LogCmd("(Mock) " + cmd, machine, username)
- return 0
-
-
-class CommandTerminator:
- def __init__(self):
- self.terminated = False
-
- def Terminate(self):
- self.terminated = True
-
- def IsTerminated(self):
- return self.terminated
diff --git a/v14/utils/constants.py b/v14/utils/constants.py
deleted file mode 100644
index 33875d66..00000000
--- a/v14/utils/constants.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/python2.6
-#
-# Copyright 2010 Google Inc. All Rights Reserved.
-
-"""Generic constants used accross modules.
-"""
-
-__author__ = "shenhan@google.com (Han Shen)"
-
-mounted_toolchain_root='/usr/local/toolchain_root'
diff --git a/v14/utils/email_sender.py b/v14/utils/email_sender.py
deleted file mode 100644
index f8c0d62c..00000000
--- a/v14/utils/email_sender.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-from email import Encoders
-from email.MIMEBase import MIMEBase
-from email.MIMEMultipart import MIMEMultipart
-from email.MIMEText import MIMEText
-import getpass
-import os
-import smtplib
-import sys
-
-
-class EmailSender(object):
- class Attachment(object):
- def __init__(self, name, content):
- self.name = name
- self.content = content
-
- def SendEmail(self,
- email_to,
- subject,
- text_to_send,
- email_cc=None,
- email_bcc=None,
- email_from=None,
- msg_type="plain",
- attachments=None):
- # Email summary to the current user.
- msg = MIMEMultipart()
-
- if not email_from:
- email_from = os.path.basename(__file__)
-
- msg["To"] = ",".join(email_to)
- msg["Subject"] = subject
-
- if email_from:
- msg["From"] = email_from
- if email_cc:
- msg["CC"] = ",".join(email_cc)
- email_to += email_cc
- if email_bcc:
- msg["BCC"] = ",".join(email_bcc)
- email_to += email_bcc
-
- msg.attach(MIMEText(text_to_send, msg_type))
- if attachments:
- for attachment in attachments:
- part = MIMEBase("application", "octet-stream")
- part.set_payload(attachment.content)
- Encoders.encode_base64(part)
- part.add_header("Content-Disposition", "attachment; filename=\"%s\"" %
- attachment.name)
- msg.attach(part)
-
- # Send the message via our own SMTP server, but don't include the
- # envelope header.
- s = smtplib.SMTP("localhost")
- s.sendmail(email_from, email_to, msg.as_string())
- s.quit()
diff --git a/v14/utils/file_utils.py b/v14/utils/file_utils.py
deleted file mode 100644
index 24809333..00000000
--- a/v14/utils/file_utils.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-import errno
-import hashlib
-import os
-import shutil
-import command_executer
-
-
-class FileUtils(object):
- """Utilities for operations on files."""
- _instance = None
- DRY_RUN = False
-
- @classmethod
- def Configure(cls, dry_run):
- cls.DRY_RUN = dry_run
-
- def __new__(cls, *args, **kwargs):
- if not cls._instance:
- if cls.DRY_RUN:
- cls._instance = super(FileUtils, cls).__new__(MockFileUtils, *args,
- **kwargs)
- else:
- cls._instance = super(FileUtils, cls).__new__(cls, *args,
- **kwargs)
- return cls._instance
-
- def Md5File(self, filename, block_size=2 ** 10):
- command = "md5sum %s" % filename
- ce = command_executer.GetCommandExecuter()
- ret, out, err = ce.RunCommand(command, return_output=True)
- if ret:
- raise Exception("Could not run md5sum on: %s" % filename)
-
- return out.strip().split()[0]
-
- def CanonicalizeChromeOSRoot(self, chromeos_root):
- chromeos_root = os.path.expanduser(chromeos_root)
- if os.path.isfile(os.path.join(chromeos_root,
- "src/scripts/run_remote_tests.sh")):
- return chromeos_root
- else:
- return None
-
- def ChromeOSRootFromImage(self, chromeos_image):
- chromeos_root = os.path.join(os.path.dirname(chromeos_image),
- "../../../../..")
- return self.CanonicalizeChromeOSRoot(chromeos_root)
-
- def MkDirP(self, path):
- try:
- os.makedirs(path)
- except OSError as exc:
- if exc.errno == errno.EEXIST:
- pass
- else:
- raise
-
- def RmDir(self, path):
- shutil.rmtree(path, ignore_errors=True)
-
- def WriteFile(self, path, contents):
- with open(path, "wb") as f:
- f.write(contents)
-
-
-class MockFileUtils(FileUtils):
- """Mock class for file utilities."""
-
- def Md5File(self, filename, block_size=2 ** 10):
- return "d41d8cd98f00b204e9800998ecf8427e"
-
- def CanonicalizeChromeOSRoot(self, chromeos_root):
- return "/tmp/chromeos_root"
-
- def ChromeOSRootFromImage(self, chromeos_image):
- return "/tmp/chromeos_root"
-
- def RmDir(self, path):
- pass
-
- def MkDirP(self, path):
- pass
-
- def WriteFile(self, path, contents):
- pass
diff --git a/v14/utils/html_tools.py b/v14/utils/html_tools.py
deleted file mode 100644
index c90a57b5..00000000
--- a/v14/utils/html_tools.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/python2.6
-#
-# Copyright 2010 Google Inc. All Rights Reserved.
-#
-
-
-def GetPageHeader(page_title):
- return """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html>
-<head>
-<style type="text/css">
-table
-{
-border-collapse:collapse;
-}
-table, td, th
-{
-border:1px solid black;
-}
-</style>
-<script type="text/javascript">
-function displayRow(id){
- var row = document.getElementById("group_"+id);
- if (row.style.display == '') row.style.display = 'none';
- else row.style.display = '';
- }
-</script>
-<title>%s</title>
-</head>
-<body>
-
-""" % page_title
-
-
-def GetListHeader():
- return "<ul>"
-
-
-def GetListItem(text):
- return "<li>%s</li>" % text
-
-
-def GetListFooter():
- return "</ul>"
-
-
-def GetList(items):
- return "<ul>%s</ul>" % "".join(["<li>%s</li>" % item for item in items])
-
-
-def GetParagraph(text):
- return "<p>%s</p>" % text
-
-
-def GetFooter():
- return "</body>\n</html>"
-
-
-def GetHeader(text, h=1):
- return "<h%s>%s</h%s>" % (h, text, h)
-
-
-def GetTableHeader(headers):
- row = "".join(["<th>%s</th>" % header for header in headers])
- return "<table><tr>%s</tr>" % row
-
-
-def GetTableFooter():
- return "</table>"
-
-
-def FormatLineBreaks(text):
- return text.replace("\n", "<br/>")
-
-
-def GetTableCell(text):
- return "<td>%s</td>" % FormatLineBreaks(str(text))
-
-
-def GetTableRow(columns):
- return "<tr>%s</tr>" % "\n".join([GetTableCell(column) for column in columns])
-
-
-def GetTable(headers, rows):
- table = [GetTableHeader(headers)]
- table.extend([GetTableRow(row) for row in rows])
- table.append(GetTableFooter())
- return "\n".join(table)
-
-
-def GetLink(link, text):
- return "<a href='%s'>%s</a>" % (link, text)
diff --git a/v14/utils/logger.py b/v14/utils/logger.py
deleted file mode 100644
index 99c679ab..00000000
--- a/v14/utils/logger.py
+++ /dev/null
@@ -1,195 +0,0 @@
-#!/usr/bin/python2.6
-#
-# Copyright 2010 Google Inc. All Rights Reserved.
-
-# System modules
-import os.path
-import sys
-import traceback
-
-#TODO(yunlian@google.com): Use GetRoot from misc
-def GetRoot(scr_name):
- """Break up pathname into (dir+name)."""
- abs_path = os.path.abspath(scr_name)
- return (os.path.dirname(abs_path), os.path.basename(abs_path))
-
-
-class Logger(object):
- """Logging helper class."""
-
- MAX_LOG_FILES = 10
-
- def __init__ (self, rootdir, basefilename, print_console, subdir="logs"):
- logdir = os.path.join(rootdir, subdir)
- basename = os.path.join(logdir, basefilename)
-
- try:
- os.makedirs(logdir)
- except OSError:
- pass
- # print "Warning: Logs directory '%s' already exists." % logdir
-
- self.print_console = print_console
-
- self._CreateLogFileHandles(basename)
-
- self._WriteTo(self.cmdfd, " ".join(sys.argv), True)
-
- def _AddSuffix(self, basename, suffix):
- return "%s%s" % (basename, suffix)
-
- def _FindSuffix(self, basename):
- timestamps = []
- found_suffix = None
- for i in range(self.MAX_LOG_FILES):
- suffix = str(i)
- suffixed_basename = self._AddSuffix(basename, suffix)
- cmd_file = "%s.cmd" % suffixed_basename
- if not os.path.exists(cmd_file):
- found_suffix = suffix
- break
- timestamps.append(os.stat(cmd_file).st_mtime)
-
- if found_suffix:
- return found_suffix
-
- # Try to pick the oldest file with the suffix and return that one.
- suffix = str(timestamps.index(min(timestamps)))
- # print ("Warning: Overwriting log file: %s" %
- # self._AddSuffix(basename, suffix))
- return suffix
-
- def _CreateLogFileHandle(self, name):
- fd = None
- try:
- fd = open(name, "w")
- except IOError:
- print "Warning: could not open %s for writing." % name
- return fd
-
- def _CreateLogFileHandles(self, basename):
- suffix = self._FindSuffix(basename)
- suffixed_basename = self._AddSuffix(basename, suffix)
-
- self.cmdfd = self._CreateLogFileHandle("%s.cmd" % suffixed_basename)
- self.stdout = self._CreateLogFileHandle("%s.out" % suffixed_basename)
- self.stderr = self._CreateLogFileHandle("%s.err" % suffixed_basename)
-
- self._CreateLogFileSymlinks(basename, suffixed_basename)
-
- # Symlink unsuffixed basename to currently suffixed one.
- def _CreateLogFileSymlinks(self, basename, suffixed_basename):
- try:
- for extension in ["cmd", "out", "err"]:
- src_file = "%s.%s" % (os.path.basename(suffixed_basename), extension)
- dest_file = "%s.%s" % (basename, extension)
- if os.path.exists(dest_file):
- os.remove(dest_file)
- os.symlink(src_file, dest_file)
- except Exception as ex:
- print "Exception while creating symlinks: %s" % str(ex)
-
- def _WriteTo(self, fd, msg, flush):
- if fd:
- fd.write(msg)
- if flush:
- fd.flush()
-
- def _LogMsg(self, file_fd, term_fd, msg, flush=True):
- if file_fd:
- self._WriteTo(file_fd, msg, flush)
- if self.print_console:
- self._WriteTo(term_fd, msg, flush)
-
- def _GetStdout(self, print_to_console):
- if print_to_console:
- return sys.stdout
- return None
-
- def _GetStderr(self, print_to_console):
- if print_to_console:
- return sys.stderr
- return None
-
- def LogCmd(self, cmd, machine="", user=None, print_to_console=True):
- if user:
- host = "%s@%s" % (user, machine)
- else:
- host = machine
-
- self._LogMsg(self.cmdfd, self._GetStdout(print_to_console),
- "CMD (%s): %s\n" % (host, cmd))
-
- def LogFatal(self, msg, print_to_console=True):
- self._LogMsg(self.stderr, self._GetStderr(print_to_console),
- "FATAL: %s\n" % msg)
- self._LogMsg(self.stderr, self._GetStderr(print_to_console),
- "\n".join(traceback.format_stack()))
- sys.exit(1)
-
- def LogError(self, msg, print_to_console=True):
- self._LogMsg(self.stderr, self._GetStderr(print_to_console),
- "ERROR: %s\n" % msg)
-
- def LogWarning(self, msg, print_to_console=True):
- self._LogMsg(self.stderr, self._GetStderr(print_to_console),
- "WARNING: %s\n" % msg)
-
- def LogOutput(self, msg, print_to_console=True):
- self._LogMsg(self.stdout, self._GetStdout(print_to_console),
- "OUTPUT: %s\n" % msg)
-
- def LogFatalIf(self, condition, msg):
- if condition:
- self.LogFatal(msg)
-
- def LogErrorIf(self, condition, msg):
- if condition:
- self.LogError(msg)
-
- def LogWarningIf(self, condition, msg):
- if condition:
- self.LogWarning(msg)
-
- def LogCommandOutput(self, msg, print_to_console=True):
- self._LogMsg(self.stdout, self._GetStdout(print_to_console),
- msg, flush=False)
-
- def LogCommandError(self, msg, print_to_console=True):
- self._LogMsg(self.stderr, self._GetStderr(print_to_console),
- msg, flush=False)
-
- def Flush(self):
- self.cmdfd.flush()
- self.stdout.flush()
- self.stderr.flush()
-
-main_logger = None
-
-
-def InitLogger(script_name, log_dir, print_console=True):
- """Initialize a global logger. To be called only once."""
- global main_logger
- assert not main_logger, "The logger has already been initialized"
- rootdir, basefilename = GetRoot(script_name)
- if not log_dir:
- log_dir = rootdir
- main_logger = Logger(log_dir, basefilename, print_console)
-
-
-def GetLogger(log_dir=""):
- if not main_logger:
- InitLogger(sys.argv[0], log_dir)
- return main_logger
-
-
-def HandleUncaughtExceptions(fun):
- """Catches all exceptions that would go outside decorated fun scope."""
-
- def _Interceptor(*args, **kwargs):
- try:
- return fun(*args, **kwargs)
- except StandardError:
- GetLogger().LogFatal("Uncaught exception:\n%s" % traceback.format_exc())
-
- return _Interceptor
diff --git a/v14/utils/misc.py b/v14/utils/misc.py
deleted file mode 100644
index 175a6e07..00000000
--- a/v14/utils/misc.py
+++ /dev/null
@@ -1,327 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2010 Google Inc. All Rights Reserved.
-
-"""Utilities for toolchain build."""
-
-__author__ = "asharif@google.com (Ahmad Sharif)"
-
-from contextlib import contextmanager
-import os
-import re
-import shutil
-import sys
-import time
-
-import lock_machine
-
-import command_executer
-import logger
-
-
-def GetChromeOSVersionFromLSBVersion(lsb_version):
- """Get Chromeos version from Lsb version."""
- ce = command_executer.GetCommandExecuter()
- command = "git ls-remote http://git.chromium.org/chromiumos/manifest.git"
- ret, out, _ = ce.RunCommand(command, return_output=True,
- print_to_console=False)
- assert ret == 0, "Command %s failed" % command
- lower = []
- for line in out.splitlines():
- mo = re.search(r"refs/heads/release-R(\d+)-(\d+)\.B", line)
- if mo:
- revision = int(mo.group(1))
- build = int(mo.group(2))
- lsb_build = int(lsb_version.split(".")[0])
- if lsb_build > build:
- lower.append(revision)
- lower = sorted(lower)
- if lower:
- return "R%d-%s" % (lower[-1] + 1, lsb_version)
- else:
- return "Unknown"
-
-
-def ApplySubs(string, *substitutions):
- for pattern, replacement in substitutions:
- string = re.sub(pattern, replacement, string)
- return string
-
-
-def UnitToNumber(unit_num, base=1000):
- """Convert a number with unit to float."""
- unit_dict = {"kilo": base,
- "mega": base**2,
- "giga": base**3}
- unit_num = unit_num.lower()
- mo = re.search(r"(\d*)(.+)?", unit_num)
- number = mo.group(1)
- unit = mo.group(2)
- if not unit:
- return float(number)
- for k, v in unit_dict.items():
- if k.startswith(unit):
- return float(number) * v
- raise Exception("Unit: %s not found in byte: %s!" %
- (unit,
- unit_num))
-
-
-def GetFilenameFromString(string):
- return ApplySubs(string,
- (r"/", "__"),
- (r"\s", "_"),
- (r"[\^\$=\"\\\?]", ""),
- )
-
-
-def GetRoot(scr_name):
- """Break up pathname into (dir+name)."""
- abs_path = os.path.abspath(scr_name)
- return (os.path.dirname(abs_path), os.path.basename(abs_path))
-
-
-def GetChromeOSKeyFile(chromeos_root):
- return os.path.join(chromeos_root,
- "src",
- "scripts",
- "mod_for_test_scripts",
- "ssh_keys",
- "testing_rsa")
-
-
-def GetChrootPath(chromeos_root):
- return os.path.join(chromeos_root,
- "chroot")
-
-
-def GetInsideChrootPath(chromeos_root, file_path):
- if not file_path.startswith(GetChrootPath(chromeos_root)):
- raise Exception("File: %s doesn't seem to be in the chroot: %s" %
- (file_path,
- chromeos_root))
- return file_path[len(GetChrootPath(chromeos_root)):]
-
-
-def GetOutsideChrootPath(chromeos_root, file_path):
- return os.path.join(GetChrootPath(chromeos_root),
- file_path.lstrip("/"))
-
-
-def FormatQuotedCommand(command):
- return ApplySubs(command,
- ("\"", "\\\""))
-
-
-def FormatCommands(commands):
- return ApplySubs(str(commands),
- ("&&", "&&\n"),
- (";", ";\n"),
- (r"\n+\s*", "\n"))
-
-
-def GetImageDir(chromeos_root, board):
- return os.path.join(chromeos_root,
- "src",
- "build",
- "images",
- board)
-
-
-def LabelLatestImage(chromeos_root, board, label):
- image_dir = GetImageDir(chromeos_root, board)
- latest_image_dir = os.path.join(image_dir, "latest")
- latest_image_dir = os.path.realpath(latest_image_dir)
- latest_image_dir = os.path.basename(latest_image_dir)
- with WorkingDirectory(image_dir):
- command = "ln -sf -T %s %s" % (latest_image_dir, label)
- ce = command_executer.GetCommandExecuter()
- return ce.RunCommand(command)
-
-
-def DoesLabelExist(chromeos_root, board, label):
- image_label = os.path.join(GetImageDir(chromeos_root, board),
- label)
- return os.path.exists(image_label)
-
-
-def GetBuildPackagesCommand(board, usepkg=False, debug=False):
- if usepkg:
- usepkg_flag = "--usepkg"
- else:
- usepkg_flag = "--nousepkg"
- if debug:
- withdebug_flag = '--withdebug'
- else:
- withdebug_flag = '--nowithdebug'
- return ("./build_packages %s --withdev --withtest --withautotest "
- "--skip_toolchain_update %s --board=%s" %
- (usepkg_flag, withdebug_flag, board))
-
-
-def GetBuildImageCommand(board, dev=False):
- dev_args = ""
- if dev:
- dev_args = "--noenable_rootfs_verification --disk_layout=2gb-rootfs"
- return "./build_image --board=%s %s test" % (board, dev_args)
-
-def GetSetupBoardCommand(board, gcc_version=None, binutils_version=None,
- usepkg=None, force=None):
- """Get setup_board command."""
- options = []
-
- if gcc_version:
- options.append("--gcc_version=%s" % gcc_version)
-
- if binutils_version:
- options.append("--binutils_version=%s" % binutils_version)
-
- if usepkg:
- options.append("--usepkg")
- else:
- options.append("--nousepkg")
-
- if force:
- options.append("--force")
-
- return "./setup_board --board=%s %s" % (board, " ".join(options))
-
-
-def CanonicalizePath(path):
- path = os.path.expanduser(path)
- path = os.path.realpath(path)
- return path
-
-
-def GetCtargetFromBoard(board, chromeos_root):
- """Get Ctarget from board."""
- base_board = board.split("_")[0]
- command = ("source "
- "../platform/dev/toolchain_utils.sh; get_ctarget_from_board %s" %
- base_board)
- ce = command_executer.GetCommandExecuter()
- ret, out, _ = ce.ChrootRunCommand(chromeos_root,
- command,
- return_output=True)
- if ret != 0:
- raise ValueError("Board %s is invalid!" % board)
- # Remove ANSI escape sequences.
- out = StripANSIEscapeSequences(out)
- return out.strip()
-
-
-def StripANSIEscapeSequences(string):
- string = re.sub(r"\x1b\[[0-9]*[a-zA-Z]", "", string)
- return string
-
-
-def GetChromeSrcDir():
- return "var/cache/distfiles/target/chrome-src/src"
-
-
-def GetEnvStringFromDict(env_dict):
- return " ".join(["%s=\"%s\"" % var for var in env_dict.items()])
-
-
-def MergeEnvStringWithDict(env_string, env_dict, prepend=True):
- """Merge env string with dict."""
- if not env_string.strip():
- return GetEnvStringFromDict(env_dict)
- override_env_list = []
- ce = command_executer.GetCommandExecuter()
- for k, v in env_dict.items():
- v = v.strip("\"'")
- if prepend:
- new_env = "%s=\"%s $%s\"" % (k, v, k)
- else:
- new_env = "%s=\"$%s %s\"" % (k, k, v)
- command = "; ".join([env_string, new_env, "echo $%s" % k])
- ret, out, _ = ce.RunCommand(command, return_output=True)
- override_env_list.append("%s=%r" % (k, out.strip()))
- ret = env_string + " " + " ".join(override_env_list)
- return ret.strip()
-
-
-def GetAllImages(chromeos_root, board):
- ce = command_executer.GetCommandExecuter()
- command = ("find %s/src/build/images/%s -name chromiumos_test_image.bin" %
- (chromeos_root, board))
- ret, out, _ = ce.RunCommand(command, return_output=True)
- assert ret == 0, "Could not run command: %s" % command
- return out.splitlines()
-
-
-def AcquireLock(lock_file, timeout=1200):
- """Acquire a lock with timeout."""
- start_time = time.time()
- locked = False
- abs_path = os.path.abspath(lock_file)
- dir_path = os.path.dirname(abs_path)
- sleep_time = min(10, timeout/10.0)
- reason = "pid: {0}, commad: {1}".format(os.getpid(),
- sys.argv[0])
- if not os.path.exists(dir_path):
- try:
- with lock_machine.FileCreationMask(0002):
- os.makedirs(dir_path)
- except OSError:
- print "Cannot create dir {0}, exiting...".format(dir_path)
- exit(0)
- while True:
- locked = (lock_machine.Lock(lock_file).NonBlockingLock(True, reason))
- if locked:
- break
- time.sleep(sleep_time)
- if time.time() - start_time > timeout:
- logger.GetLogger().LogWarning(
- "Could not acquire lock on this file: {0} within {1} seconds."
- "Manually remove the file if you think the lock is stale"
- .format(abs_path, timeout))
- break
- return locked
-
-
-def ReleaseLock(lock_file):
- lock_file = os.path.abspath(lock_file)
- ret = lock_machine.Lock(lock_file).Unlock(True)
- assert ret, ("Could not unlock {0},"
- "Please remove it manually".format(lock_file))
-
-
-def IsFloat(text):
- if text is None:
- return False
- try:
- float(text)
- return True
- except ValueError:
- return False
-
-def RemoveChromeBrowserObjectFiles(chromeos_root, board):
- """ Remove any object files from all the posible locations """
- out_dir = os.path.join(
- GetChrootPath(chromeos_root),
- "var/cache/chromeos-chrome/chrome-src/src/out_%s" % board)
- if os.path.exists(out_dir):
- shutil.rmtree(out_dir)
- logger.GetLogger().LogCmd("rm -rf %s" % out_dir)
- out_dir = os.path.join(
- GetChrootPath(chromeos_root),
- "var/cache/chromeos-chrome/chrome-src-internal/src/out_%s" % board)
- if os.path.exists(out_dir):
- shutil.rmtree(out_dir)
- logger.GetLogger().LogCmd("rm -rf %s" % out_dir)
-
-@contextmanager
-def WorkingDirectory(new_dir):
- """Get the working directory."""
- old_dir = os.getcwd()
- if old_dir != new_dir:
- msg = "cd %s" % new_dir
- logger.GetLogger().LogCmd(msg)
- os.chdir(new_dir)
- yield new_dir
- if old_dir != new_dir:
- msg = "cd %s" % old_dir
- logger.GetLogger().LogCmd(msg)
- os.chdir(old_dir)
diff --git a/v14/utils/misc_test.py b/v14/utils/misc_test.py
deleted file mode 100644
index e234332f..00000000
--- a/v14/utils/misc_test.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright 2012 Google Inc. All Rights Reserved.
-
-"""Tests for misc."""
-
-__author__ = 'asharif@google.com (Ahmad Sharif)'
-
-# System modules
-import re
-import unittest
-
-# Local modules
-import misc
-
-
-class UtilsTest(unittest.TestCase):
- def testGetFilenameFromString(self):
- string = 'a /b=c"d^$?\\'
- filename = misc.GetFilenameFromString(string)
- self.assertTrue(filename == 'a___bcd')
-
- def testPrependMergeEnv(self):
- var = 'USE'
- use_flags = 'hello 123'
- added_use_flags = 'bla bla'
- env_string = '%s=%r' % (var, use_flags)
- new_env_string = misc.MergeEnvStringWithDict(env_string,
- {var: added_use_flags})
- expected_new_env = '%s=%r' % (var, ' '.join([added_use_flags, use_flags]))
- self.assertTrue(new_env_string == ' '.join([env_string, expected_new_env]))
-
- def testGetChromeOSVersionFromLSBVersion(self):
- versions_dict = {"2630.0.0": "22",
- "2030.0.0": "19"}
- f = misc.GetChromeOSVersionFromLSBVersion
- for k, v in versions_dict.items():
- self.assertTrue(f(k) == "R%s-%s" % (v, k))
-
- def testPostpendMergeEnv(self):
- var = 'USE'
- use_flags = 'hello 123'
- added_use_flags = 'bla bla'
- env_string = '%s=%r' % (var, use_flags)
- new_env_string = misc.MergeEnvStringWithDict(env_string,
- {var: added_use_flags},
- False)
- expected_new_env = '%s=%r' % (var, ' '.join([use_flags, added_use_flags]))
- self.assertTrue(new_env_string == ' '.join([env_string, expected_new_env]))
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/v14/utils/perf_diff.py b/v14/utils/perf_diff.py
deleted file mode 100755
index d56eba16..00000000
--- a/v14/utils/perf_diff.py
+++ /dev/null
@@ -1,324 +0,0 @@
-#!/usr/bin/python
-# Copyright 2012 Google Inc. All Rights Reserved.
-
-"""One-line documentation for perf_diff module.
-
-A detailed description of perf_diff.
-"""
-
-__author__ = "asharif@google.com (Ahmad Sharif)"
-
-import optparse
-import re
-import sys
-
-import misc
-import tabulator
-
-ROWS_TO_SHOW = "Rows_to_show_in_the_perf_table"
-
-def GetPerfDictFromReport(report_file):
- output = {}
- perf_report = PerfReport(report_file)
- for k, v in perf_report.sections.items():
- if k not in output:
- output[k] = {}
- output[k][ROWS_TO_SHOW] = 0
- for function in v.functions:
- out_key = "%s" % (function.name)
- output[k][out_key] = function.count
- if function.percent > 1:
- output[k][ROWS_TO_SHOW] += 1
- return output
-
-
-def _SortDictionaryByValue(d):
- l = [(k, v) for (k, v) in d.iteritems()]
-
- def GetFloat(x):
- if misc.IsFloat(x):
- return float(x)
- else:
- return x
-
- sorted_l = sorted(l,
- key=lambda x: GetFloat(x[1]))
- sorted_l.reverse()
- return [f[0] for f in sorted_l]
-
-
-class Tabulator(object):
- def __init__(self, all_dicts):
- self._all_dicts = all_dicts
-
- def PrintTable(self):
- for dicts in self._all_dicts:
- self.PrintTableHelper(dicts)
-
- def PrintTableHelper(self, dicts):
- """Transfrom dicts to tables."""
- fields = {}
- for d in dicts:
- for f in d.keys():
- if f not in fields:
- fields[f] = d[f]
- else:
- fields[f] = max(fields[f], d[f])
- table = []
- header = ["name"]
- for i in range(len(dicts)):
- header.append(i)
-
- table.append(header)
-
- sorted_fields = _SortDictionaryByValue(fields)
-
- for f in sorted_fields:
- row = [f]
- for d in dicts:
- if f in d:
- row.append(d[f])
- else:
- row.append("0")
- table.append(row)
-
- print tabulator.GetSimpleTable(table)
-
-
-class Function(object):
- def __init__(self):
- self.count = 0
- self.name = ""
- self.percent = 0
-
-
-class Section(object):
- def __init__(self, contents):
- self.raw_contents = contents
- self._ParseSection()
-
- def _ParseSection(self):
- matches = re.findall(r"Events: (\w+)\s+(.*)", self.raw_contents)
- assert len(matches) <= 1, "More than one event found in 1 section"
- if not matches:
- return
- match = matches[0]
- self.name = match[1]
- self.count = misc.UnitToNumber(match[0])
-
- self.functions = []
- for line in self.raw_contents.splitlines():
- if not line.strip():
- continue
- if "%" not in line:
- continue
- if not line.startswith("#"):
- fields = [f for f in line.split(" ") if f]
- function = Function()
- function.percent = float(fields[0].strip("%"))
- function.count = int(fields[1])
- function.name = " ".join(fields[2:])
- self.functions.append(function)
-
-
-class PerfReport(object):
- """Get report from raw report."""
-
- def __init__(self, perf_file):
- self.perf_file = perf_file
- self._ReadFile()
- self.sections = {}
- self.metadata = {}
- self._section_contents = []
- self._section_header = ""
- self._SplitSections()
- self._ParseSections()
- self._ParseSectionHeader()
-
- def _ParseSectionHeader(self):
- """Parse a header of a perf report file."""
- # The "captured on" field is inaccurate - this actually refers to when the
- # report was generated, not when the data was captured.
- for line in self._section_header.splitlines():
- line = line[2:]
- if ":" in line:
- key, val = line.strip().split(":", 1)
- key = key.strip()
- val = val.strip()
- self.metadata[key] = val
-
- def _ReadFile(self):
- self._perf_contents = open(self.perf_file).read()
-
- def _ParseSections(self):
- self.event_counts = {}
- self.sections = {}
- for section_content in self._section_contents:
- section = Section(section_content)
- section.name = self._GetHumanReadableName(section.name)
- self.sections[section.name] = section
-
- # TODO(asharif): Do this better.
- def _GetHumanReadableName(self, section_name):
- if not "raw" in section_name:
- return section_name
- raw_number = section_name.strip().split(" ")[-1]
- for line in self._section_header.splitlines():
- if raw_number in line:
- name = line.strip().split(" ")[5]
- return name
-
- def _SplitSections(self):
- self._section_contents = []
- indices = [m.start() for m in re.finditer("# Events:", self._perf_contents)]
- indices.append(len(self._perf_contents))
- for i in range(len(indices) - 1):
- section_content = self._perf_contents[indices[i]:indices[i+1]]
- self._section_contents.append(section_content)
- self._section_header = ""
- if indices:
- self._section_header = self._perf_contents[0:indices[0]]
-
-
-class PerfDiffer(object):
- """Perf differ class."""
-
- def __init__(self, reports, num_symbols, common_only):
- self._reports = reports
- self._num_symbols = num_symbols
- self._common_only = common_only
- self._common_function_names = {}
-
- def DoDiff(self):
- """The function that does the diff."""
- section_names = self._FindAllSections()
-
- filename_dicts = []
- summary_dicts = []
- for report in self._reports:
- d = {}
- filename_dicts.append({"file": report.perf_file})
- for section_name in section_names:
- if section_name in report.sections:
- d[section_name] = report.sections[section_name].count
- summary_dicts.append(d)
-
- all_dicts = [filename_dicts, summary_dicts]
-
- for section_name in section_names:
- function_names = self._GetTopFunctions(section_name,
- self._num_symbols)
- self._FindCommonFunctions(section_name)
- dicts = []
- for report in self._reports:
- d = {}
- if section_name in report.sections:
- section = report.sections[section_name]
-
- # Get a common scaling factor for this report.
- common_scaling_factor = self._GetCommonScalingFactor(section)
-
- for function in section.functions:
- if function.name in function_names:
- key = "%s %s" % (section.name, function.name)
- d[key] = function.count
- # Compute a factor to scale the function count by in common_only
- # mode.
- if self._common_only and (
- function.name in self._common_function_names[section.name]):
- d[key + " scaled"] = common_scaling_factor * function.count
- dicts.append(d)
-
- all_dicts.append(dicts)
-
- mytabulator = Tabulator(all_dicts)
- mytabulator.PrintTable()
-
- def _FindAllSections(self):
- sections = {}
- for report in self._reports:
- for section in report.sections.values():
- if section.name not in sections:
- sections[section.name] = section.count
- else:
- sections[section.name] = max(sections[section.name],
- section.count)
- return _SortDictionaryByValue(sections)
-
- def _GetCommonScalingFactor(self, section):
- unique_count = self._GetCount(
- section,
- lambda x: x in self._common_function_names[section.name])
- return 100.0/unique_count
-
- def _GetCount(self, section, filter_fun=None):
- total_count = 0
- for function in section.functions:
- if not filter_fun or filter_fun(function.name):
- total_count += int(function.count)
- return total_count
-
- def _FindCommonFunctions(self, section_name):
- function_names_list = []
- for report in self._reports:
- if section_name in report.sections:
- section = report.sections[section_name]
- function_names = [f.name for f in section.functions]
- function_names_list.append(function_names)
-
- self._common_function_names[section_name] = (
- reduce(set.intersection, map(set, function_names_list)))
-
- def _GetTopFunctions(self, section_name, num_functions):
- all_functions = {}
- for report in self._reports:
- if section_name in report.sections:
- section = report.sections[section_name]
- for f in section.functions[:num_functions]:
- if f.name in all_functions:
- all_functions[f.name] = max(all_functions[f.name], f.count)
- else:
- all_functions[f.name] = f.count
- # FIXME(asharif): Don't really need to sort these...
- return _SortDictionaryByValue(all_functions)
-
- def _GetFunctionsDict(self, section, function_names):
- d = {}
- for function in section.functions:
- if function.name in function_names:
- d[function.name] = function.count
- return d
-
-
-def Main(argv):
- """The entry of the main."""
- parser = optparse.OptionParser()
- parser.add_option("-n",
- "--num_symbols",
- dest="num_symbols",
- default="5",
- help="The number of symbols to show.")
- parser.add_option("-c",
- "--common_only",
- dest="common_only",
- action="store_true",
- default=False,
- help="Diff common symbols only.")
-
- options, args = parser.parse_args(argv)
-
- try:
- reports = []
- for report in args[1:]:
- report = PerfReport(report)
- reports.append(report)
- pd = PerfDiffer(reports, int(options.num_symbols), options.common_only)
- pd.DoDiff()
- finally:
- pass
-
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(Main(sys.argv))
diff --git a/v14/utils/pstat.py b/v14/utils/pstat.py
deleted file mode 100644
index dae681e6..00000000
--- a/v14/utils/pstat.py
+++ /dev/null
@@ -1,1068 +0,0 @@
-# Copyright (c) 1999-2007 Gary Strangman; All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-# Comments and/or additions are welcome (send e-mail to:
-# strang@nmr.mgh.harvard.edu).
-#
-"""
-pstat.py module
-
-#################################################
-####### Written by: Gary Strangman ###########
-####### Last modified: Dec 18, 2007 ###########
-#################################################
-
-This module provides some useful list and array manipulation routines
-modeled after those found in the |Stat package by Gary Perlman, plus a
-number of other useful list/file manipulation functions. The list-based
-functions include:
-
- abut (source,*args)
- simpleabut (source, addon)
- colex (listoflists,cnums)
- collapse (listoflists,keepcols,collapsecols,fcn1=None,fcn2=None,cfcn=None)
- dm (listoflists,criterion)
- flat (l)
- linexand (listoflists,columnlist,valuelist)
- linexor (listoflists,columnlist,valuelist)
- linedelimited (inlist,delimiter)
- lineincols (inlist,colsize)
- lineincustcols (inlist,colsizes)
- list2string (inlist)
- makelol(inlist)
- makestr(x)
- printcc (lst,extra=2)
- printincols (listoflists,colsize)
- pl (listoflists)
- printl(listoflists)
- replace (lst,oldval,newval)
- recode (inlist,listmap,cols='all')
- remap (listoflists,criterion)
- roundlist (inlist,num_digits_to_round_floats_to)
- sortby(listoflists,sortcols)
- unique (inlist)
- duplicates(inlist)
- writedelimited (listoflists, delimiter, file, writetype='w')
-
-Some of these functions have alternate versions which are defined only if
-Numeric (NumPy) can be imported. These functions are generally named as
-above, with an 'a' prefix.
-
- aabut (source, *args)
- acolex (a,indices,axis=1)
- acollapse (a,keepcols,collapsecols,sterr=0,ns=0)
- adm (a,criterion)
- alinexand (a,columnlist,valuelist)
- alinexor (a,columnlist,valuelist)
- areplace (a,oldval,newval)
- arecode (a,listmap,col='all')
- arowcompare (row1, row2)
- arowsame (row1, row2)
- asortrows(a,axis=0)
- aunique(inarray)
- aduplicates(inarray)
-
-Currently, the code is all but completely un-optimized. In many cases, the
-array versions of functions amount simply to aliases to built-in array
-functions/methods. Their inclusion here is for function name consistency.
-"""
-
-## CHANGE LOG:
-## ==========
-## 07-11-26 ... edited to work with numpy
-## 01-11-15 ... changed list2string() to accept a delimiter
-## 01-06-29 ... converted exec()'s to eval()'s to make compatible with Py2.1
-## 01-05-31 ... added duplicates() and aduplicates() functions
-## 00-12-28 ... license made GPL, docstring and import requirements
-## 99-11-01 ... changed version to 0.3
-## 99-08-30 ... removed get, getstrings, put, aget, aput (into io.py)
-## 03/27/99 ... added areplace function, made replace fcn recursive
-## 12/31/98 ... added writefc function for ouput to fixed column sizes
-## 12/07/98 ... fixed import problem (failed on collapse() fcn)
-## added __version__ variable (now 0.2)
-## 12/05/98 ... updated doc-strings
-## added features to collapse() function
-## added flat() function for lists
-## fixed a broken asortrows()
-## 11/16/98 ... fixed minor bug in aput for 1D arrays
-##
-## 11/08/98 ... fixed aput to output large arrays correctly
-
-import stats # required 3rd party module
-import string, copy
-from types import *
-
-__version__ = 0.4
-
-###=========================== LIST FUNCTIONS ==========================
-###
-### Here are the list functions, DEFINED FOR ALL SYSTEMS.
-### Array functions (for NumPy-enabled computers) appear below.
-###
-
-def abut (source,*args):
- """
-Like the |Stat abut command. It concatenates two lists side-by-side
-and returns the result. '2D' lists are also accomodated for either argument
-(source or addon). CAUTION: If one list is shorter, it will be repeated
-until it is as long as the longest list. If this behavior is not desired,
-use pstat.simpleabut().
-
-Usage: abut(source, args) where args=any # of lists
-Returns: a list of lists as long as the LONGEST list past, source on the
- 'left', lists in <args> attached consecutively on the 'right'
-"""
-
- if type(source) not in [ListType,TupleType]:
- source = [source]
- for addon in args:
- if type(addon) not in [ListType,TupleType]:
- addon = [addon]
- if len(addon) < len(source): # is source list longer?
- if len(source) % len(addon) == 0: # are they integer multiples?
- repeats = len(source)/len(addon) # repeat addon n times
- origadd = copy.deepcopy(addon)
- for i in range(repeats-1):
- addon = addon + origadd
- else:
- repeats = len(source)/len(addon)+1 # repeat addon x times,
- origadd = copy.deepcopy(addon) # x is NOT an integer
- for i in range(repeats-1):
- addon = addon + origadd
- addon = addon[0:len(source)]
- elif len(source) < len(addon): # is addon list longer?
- if len(addon) % len(source) == 0: # are they integer multiples?
- repeats = len(addon)/len(source) # repeat source n times
- origsour = copy.deepcopy(source)
- for i in range(repeats-1):
- source = source + origsour
- else:
- repeats = len(addon)/len(source)+1 # repeat source x times,
- origsour = copy.deepcopy(source) # x is NOT an integer
- for i in range(repeats-1):
- source = source + origsour
- source = source[0:len(addon)]
-
- source = simpleabut(source,addon)
- return source
-
-
-def simpleabut (source, addon):
- """
-Concatenates two lists as columns and returns the result. '2D' lists
-are also accomodated for either argument (source or addon). This DOES NOT
-repeat either list to make the 2 lists of equal length. Beware of list pairs
-with different lengths ... the resulting list will be the length of the
-FIRST list passed.
-
-Usage: simpleabut(source,addon) where source, addon=list (or list-of-lists)
-Returns: a list of lists as long as source, with source on the 'left' and
- addon on the 'right'
-"""
- if type(source) not in [ListType,TupleType]:
- source = [source]
- if type(addon) not in [ListType,TupleType]:
- addon = [addon]
- minlen = min(len(source),len(addon))
- list = copy.deepcopy(source) # start abut process
- if type(source[0]) not in [ListType,TupleType]:
- if type(addon[0]) not in [ListType,TupleType]:
- for i in range(minlen):
- list[i] = [source[i]] + [addon[i]] # source/addon = column
- else:
- for i in range(minlen):
- list[i] = [source[i]] + addon[i] # addon=list-of-lists
- else:
- if type(addon[0]) not in [ListType,TupleType]:
- for i in range(minlen):
- list[i] = source[i] + [addon[i]] # source=list-of-lists
- else:
- for i in range(minlen):
- list[i] = source[i] + addon[i] # source/addon = list-of-lists
- source = list
- return source
-
-
-def colex (listoflists,cnums):
- """
-Extracts from listoflists the columns specified in the list 'cnums'
-(cnums can be an integer, a sequence of integers, or a string-expression that
-corresponds to a slice operation on the variable x ... e.g., 'x[3:]' will colex
-columns 3 onward from the listoflists).
-
-Usage: colex (listoflists,cnums)
-Returns: a list-of-lists corresponding to the columns from listoflists
- specified by cnums, in the order the column numbers appear in cnums
-"""
- global index
- column = 0
- if type(cnums) in [ListType,TupleType]: # if multiple columns to get
- index = cnums[0]
- column = map(lambda x: x[index], listoflists)
- for col in cnums[1:]:
- index = col
- column = abut(column,map(lambda x: x[index], listoflists))
- elif type(cnums) == StringType: # if an 'x[3:]' type expr.
- evalstring = 'map(lambda x: x'+cnums+', listoflists)'
- column = eval(evalstring)
- else: # else it's just 1 col to get
- index = cnums
- column = map(lambda x: x[index], listoflists)
- return column
-
-
-def collapse (listoflists,keepcols,collapsecols,fcn1=None,fcn2=None,cfcn=None):
- """
-Averages data in collapsecol, keeping all unique items in keepcols
-(using unique, which keeps unique LISTS of column numbers), retaining the
-unique sets of values in keepcols, the mean for each. Setting fcn1
-and/or fcn2 to point to a function rather than None (e.g., stats.sterr, len)
-will append those results (e.g., the sterr, N) after each calculated mean.
-cfcn is the collapse function to apply (defaults to mean, defined here in the
-pstat module to avoid circular imports with stats.py, but harmonicmean or
-others could be passed).
-
-Usage: collapse (listoflists,keepcols,collapsecols,fcn1=None,fcn2=None,cfcn=None)
-Returns: a list of lists with all unique permutations of entries appearing in
- columns ("conditions") specified by keepcols, abutted with the result of
- cfcn (if cfcn=None, defaults to the mean) of each column specified by
- collapsecols.
-"""
- def collmean (inlist):
- s = 0
- for item in inlist:
- s = s + item
- return s/float(len(inlist))
-
- if type(keepcols) not in [ListType,TupleType]:
- keepcols = [keepcols]
- if type(collapsecols) not in [ListType,TupleType]:
- collapsecols = [collapsecols]
- if cfcn == None:
- cfcn = collmean
- if keepcols == []:
- means = [0]*len(collapsecols)
- for i in range(len(collapsecols)):
- avgcol = colex(listoflists,collapsecols[i])
- means[i] = cfcn(avgcol)
- if fcn1:
- try:
- test = fcn1(avgcol)
- except:
- test = 'N/A'
- means[i] = [means[i], test]
- if fcn2:
- try:
- test = fcn2(avgcol)
- except:
- test = 'N/A'
- try:
- means[i] = means[i] + [len(avgcol)]
- except TypeError:
- means[i] = [means[i],len(avgcol)]
- return means
- else:
- values = colex(listoflists,keepcols)
- uniques = unique(values)
- uniques.sort()
- newlist = []
- if type(keepcols) not in [ListType,TupleType]: keepcols = [keepcols]
- for item in uniques:
- if type(item) not in [ListType,TupleType]: item =[item]
- tmprows = linexand(listoflists,keepcols,item)
- for col in collapsecols:
- avgcol = colex(tmprows,col)
- item.append(cfcn(avgcol))
- if fcn1 <> None:
- try:
- test = fcn1(avgcol)
- except:
- test = 'N/A'
- item.append(test)
- if fcn2 <> None:
- try:
- test = fcn2(avgcol)
- except:
- test = 'N/A'
- item.append(test)
- newlist.append(item)
- return newlist
-
-
-def dm (listoflists,criterion):
- """
-Returns rows from the passed list of lists that meet the criteria in
-the passed criterion expression (a string as a function of x; e.g., 'x[3]>=9'
-will return all rows where the 4th column>=9 and "x[2]=='N'" will return rows
-with column 2 equal to the string 'N').
-
-Usage: dm (listoflists, criterion)
-Returns: rows from listoflists that meet the specified criterion.
-"""
- function = 'filter(lambda x: '+criterion+',listoflists)'
- lines = eval(function)
- return lines
-
-
-def flat(l):
- """
-Returns the flattened version of a '2D' list. List-correlate to the a.ravel()()
-method of NumPy arrays.
-
-Usage: flat(l)
-"""
- newl = []
- for i in range(len(l)):
- for j in range(len(l[i])):
- newl.append(l[i][j])
- return newl
-
-
-def linexand (listoflists,columnlist,valuelist):
- """
-Returns the rows of a list of lists where col (from columnlist) = val
-(from valuelist) for EVERY pair of values (columnlist[i],valuelists[i]).
-len(columnlist) must equal len(valuelist).
-
-Usage: linexand (listoflists,columnlist,valuelist)
-Returns: the rows of listoflists where columnlist[i]=valuelist[i] for ALL i
-"""
- if type(columnlist) not in [ListType,TupleType]:
- columnlist = [columnlist]
- if type(valuelist) not in [ListType,TupleType]:
- valuelist = [valuelist]
- criterion = ''
- for i in range(len(columnlist)):
- if type(valuelist[i])==StringType:
- critval = '\'' + valuelist[i] + '\''
- else:
- critval = str(valuelist[i])
- criterion = criterion + ' x['+str(columnlist[i])+']=='+critval+' and'
- criterion = criterion[0:-3] # remove the "and" after the last crit
- function = 'filter(lambda x: '+criterion+',listoflists)'
- lines = eval(function)
- return lines
-
-
-def linexor (listoflists,columnlist,valuelist):
- """
-Returns the rows of a list of lists where col (from columnlist) = val
-(from valuelist) for ANY pair of values (colunmlist[i],valuelist[i[).
-One value is required for each column in columnlist. If only one value
-exists for columnlist but multiple values appear in valuelist, the
-valuelist values are all assumed to pertain to the same column.
-
-Usage: linexor (listoflists,columnlist,valuelist)
-Returns: the rows of listoflists where columnlist[i]=valuelist[i] for ANY i
-"""
- if type(columnlist) not in [ListType,TupleType]:
- columnlist = [columnlist]
- if type(valuelist) not in [ListType,TupleType]:
- valuelist = [valuelist]
- criterion = ''
- if len(columnlist) == 1 and len(valuelist) > 1:
- columnlist = columnlist*len(valuelist)
- for i in range(len(columnlist)): # build an exec string
- if type(valuelist[i])==StringType:
- critval = '\'' + valuelist[i] + '\''
- else:
- critval = str(valuelist[i])
- criterion = criterion + ' x['+str(columnlist[i])+']=='+critval+' or'
- criterion = criterion[0:-2] # remove the "or" after the last crit
- function = 'filter(lambda x: '+criterion+',listoflists)'
- lines = eval(function)
- return lines
-
-
-def linedelimited (inlist,delimiter):
- """
-Returns a string composed of elements in inlist, with each element
-separated by 'delimiter.' Used by function writedelimited. Use '\t'
-for tab-delimiting.
-
-Usage: linedelimited (inlist,delimiter)
-"""
- outstr = ''
- for item in inlist:
- if type(item) <> StringType:
- item = str(item)
- outstr = outstr + item + delimiter
- outstr = outstr[0:-1]
- return outstr
-
-
-def lineincols (inlist,colsize):
- """
-Returns a string composed of elements in inlist, with each element
-right-aligned in columns of (fixed) colsize.
-
-Usage: lineincols (inlist,colsize) where colsize is an integer
-"""
- outstr = ''
- for item in inlist:
- if type(item) <> StringType:
- item = str(item)
- size = len(item)
- if size <= colsize:
- for i in range(colsize-size):
- outstr = outstr + ' '
- outstr = outstr + item
- else:
- outstr = outstr + item[0:colsize+1]
- return outstr
-
-
-def lineincustcols (inlist,colsizes):
- """
-Returns a string composed of elements in inlist, with each element
-right-aligned in a column of width specified by a sequence colsizes. The
-length of colsizes must be greater than or equal to the number of columns
-in inlist.
-
-Usage: lineincustcols (inlist,colsizes)
-Returns: formatted string created from inlist
-"""
- outstr = ''
- for i in range(len(inlist)):
- if type(inlist[i]) <> StringType:
- item = str(inlist[i])
- else:
- item = inlist[i]
- size = len(item)
- if size <= colsizes[i]:
- for j in range(colsizes[i]-size):
- outstr = outstr + ' '
- outstr = outstr + item
- else:
- outstr = outstr + item[0:colsizes[i]+1]
- return outstr
-
-
-def list2string (inlist,delimit=' '):
- """
-Converts a 1D list to a single long string for file output, using
-the string.join function.
-
-Usage: list2string (inlist,delimit=' ')
-Returns: the string created from inlist
-"""
- stringlist = map(makestr,inlist)
- return string.join(stringlist,delimit)
-
-
-def makelol(inlist):
- """
-Converts a 1D list to a 2D list (i.e., a list-of-lists). Useful when you
-want to use put() to write a 1D list one item per line in the file.
-
-Usage: makelol(inlist)
-Returns: if l = [1,2,'hi'] then returns [[1],[2],['hi']] etc.
-"""
- x = []
- for item in inlist:
- x.append([item])
- return x
-
-
-def makestr (x):
- if type(x) <> StringType:
- x = str(x)
- return x
-
-
-def printcc (lst,extra=2):
- """
-Prints a list of lists in columns, customized by the max size of items
-within the columns (max size of items in col, plus 'extra' number of spaces).
-Use 'dashes' or '\\n' in the list-of-lists to print dashes or blank lines,
-respectively.
-
-Usage: printcc (lst,extra=2)
-Returns: None
-"""
- if type(lst[0]) not in [ListType,TupleType]:
- lst = [lst]
- rowstokill = []
- list2print = copy.deepcopy(lst)
- for i in range(len(lst)):
- if lst[i] == ['\n'] or lst[i]=='\n' or lst[i]=='dashes' or lst[i]=='' or lst[i]==['']:
- rowstokill = rowstokill + [i]
- rowstokill.reverse() # delete blank rows from the end
- for row in rowstokill:
- del list2print[row]
- maxsize = [0]*len(list2print[0])
- for col in range(len(list2print[0])):
- items = colex(list2print,col)
- items = map(makestr,items)
- maxsize[col] = max(map(len,items)) + extra
- for row in lst:
- if row == ['\n'] or row == '\n' or row == '' or row == ['']:
- print
- elif row == ['dashes'] or row == 'dashes':
- dashes = [0]*len(maxsize)
- for j in range(len(maxsize)):
- dashes[j] = '-'*(maxsize[j]-2)
- print lineincustcols(dashes,maxsize)
- else:
- print lineincustcols(row,maxsize)
- return None
-
-
-def printincols (listoflists,colsize):
- """
-Prints a list of lists in columns of (fixed) colsize width, where
-colsize is an integer.
-
-Usage: printincols (listoflists,colsize)
-Returns: None
-"""
- for row in listoflists:
- print lineincols(row,colsize)
- return None
-
-
-def pl (listoflists):
- """
-Prints a list of lists, 1 list (row) at a time.
-
-Usage: pl(listoflists)
-Returns: None
-"""
- for row in listoflists:
- if row[-1] == '\n':
- print row,
- else:
- print row
- return None
-
-
-def printl(listoflists):
- """Alias for pl."""
- pl(listoflists)
- return
-
-
-def replace (inlst,oldval,newval):
- """
-Replaces all occurrences of 'oldval' with 'newval', recursively.
-
-Usage: replace (inlst,oldval,newval)
-"""
- lst = inlst*1
- for i in range(len(lst)):
- if type(lst[i]) not in [ListType,TupleType]:
- if lst[i]==oldval: lst[i]=newval
- else:
- lst[i] = replace(lst[i],oldval,newval)
- return lst
-
-
-def recode (inlist,listmap,cols=None):
- """
-Changes the values in a list to a new set of values (useful when
-you need to recode data from (e.g.) strings to numbers. cols defaults
-to None (meaning all columns are recoded).
-
-Usage: recode (inlist,listmap,cols=None) cols=recode cols, listmap=2D list
-Returns: inlist with the appropriate values replaced with new ones
-"""
- lst = copy.deepcopy(inlist)
- if cols != None:
- if type(cols) not in [ListType,TupleType]:
- cols = [cols]
- for col in cols:
- for row in range(len(lst)):
- try:
- idx = colex(listmap,0).index(lst[row][col])
- lst[row][col] = listmap[idx][1]
- except ValueError:
- pass
- else:
- for row in range(len(lst)):
- for col in range(len(lst)):
- try:
- idx = colex(listmap,0).index(lst[row][col])
- lst[row][col] = listmap[idx][1]
- except ValueError:
- pass
- return lst
-
-
-def remap (listoflists,criterion):
- """
-Remaps values in a given column of a 2D list (listoflists). This requires
-a criterion as a function of 'x' so that the result of the following is
-returned ... map(lambda x: 'criterion',listoflists).
-
-Usage: remap(listoflists,criterion) criterion=string
-Returns: remapped version of listoflists
-"""
- function = 'map(lambda x: '+criterion+',listoflists)'
- lines = eval(function)
- return lines
-
-
-def roundlist (inlist,digits):
- """
-Goes through each element in a 1D or 2D inlist, and applies the following
-function to all elements of FloatType ... round(element,digits).
-
-Usage: roundlist(inlist,digits)
-Returns: list with rounded floats
-"""
- if type(inlist[0]) in [IntType, FloatType]:
- inlist = [inlist]
- l = inlist*1
- for i in range(len(l)):
- for j in range(len(l[i])):
- if type(l[i][j])==FloatType:
- l[i][j] = round(l[i][j],digits)
- return l
-
-
-def sortby(listoflists,sortcols):
- """
-Sorts a list of lists on the column(s) specified in the sequence
-sortcols.
-
-Usage: sortby(listoflists,sortcols)
-Returns: sorted list, unchanged column ordering
-"""
- newlist = abut(colex(listoflists,sortcols),listoflists)
- newlist.sort()
- try:
- numcols = len(sortcols)
- except TypeError:
- numcols = 1
- crit = '[' + str(numcols) + ':]'
- newlist = colex(newlist,crit)
- return newlist
-
-
-def unique (inlist):
- """
-Returns all unique items in the passed list. If the a list-of-lists
-is passed, unique LISTS are found (i.e., items in the first dimension are
-compared).
-
-Usage: unique (inlist)
-Returns: the unique elements (or rows) in inlist
-"""
- uniques = []
- for item in inlist:
- if item not in uniques:
- uniques.append(item)
- return uniques
-
-def duplicates(inlist):
- """
-Returns duplicate items in the FIRST dimension of the passed list.
-
-Usage: duplicates (inlist)
-"""
- dups = []
- for i in range(len(inlist)):
- if inlist[i] in inlist[i+1:]:
- dups.append(inlist[i])
- return dups
-
-
-def nonrepeats(inlist):
- """
-Returns items that are NOT duplicated in the first dim of the passed list.
-
-Usage: nonrepeats (inlist)
-"""
- nonrepeats = []
- for i in range(len(inlist)):
- if inlist.count(inlist[i]) == 1:
- nonrepeats.append(inlist[i])
- return nonrepeats
-
-
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-#=================== PSTAT ARRAY FUNCTIONS =====================
-
-try: # DEFINE THESE *ONLY* IF numpy IS AVAILABLE
- import numpy as N
-
- def aabut (source, *args):
- """
-Like the |Stat abut command. It concatenates two arrays column-wise
-and returns the result. CAUTION: If one array is shorter, it will be
-repeated until it is as long as the other.
-
-Usage: aabut (source, args) where args=any # of arrays
-Returns: an array as long as the LONGEST array past, source appearing on the
- 'left', arrays in <args> attached on the 'right'.
-"""
- if len(source.shape)==1:
- width = 1
- source = N.resize(source,[source.shape[0],width])
- else:
- width = source.shape[1]
- for addon in args:
- if len(addon.shape)==1:
- width = 1
- addon = N.resize(addon,[source.shape[0],width])
- else:
- width = source.shape[1]
- if len(addon) < len(source):
- addon = N.resize(addon,[source.shape[0],addon.shape[1]])
- elif len(source) < len(addon):
- source = N.resize(source,[addon.shape[0],source.shape[1]])
- source = N.concatenate((source,addon),1)
- return source
-
-
- def acolex (a,indices,axis=1):
- """
-Extracts specified indices (a list) from passed array, along passed
-axis (column extraction is default). BEWARE: A 1D array is presumed to be a
-column-array (and that the whole array will be returned as a column).
-
-Usage: acolex (a,indices,axis=1)
-Returns: the columns of a specified by indices
-"""
- if type(indices) not in [ListType,TupleType,N.ndarray]:
- indices = [indices]
- if len(N.shape(a)) == 1:
- cols = N.resize(a,[a.shape[0],1])
- else:
-# print a[:3]
- cols = N.take(a,indices,axis)
-# print cols[:3]
- return cols
-
-
- def acollapse (a,keepcols,collapsecols,fcn1=None,fcn2=None,cfcn=None):
- """
-Averages data in collapsecol, keeping all unique items in keepcols
-(using unique, which keeps unique LISTS of column numbers), retaining
-the unique sets of values in keepcols, the mean for each. If stderror or
-N of the mean are desired, set either or both parameters to 1.
-
-Usage: acollapse (a,keepcols,collapsecols,fcn1=None,fcn2=None,cfcn=None)
-Returns: unique 'conditions' specified by the contents of columns specified
- by keepcols, abutted with the mean(s) of column(s) specified by
- collapsecols
-"""
- def acollmean (inarray):
- return N.sum(N.ravel(inarray))
-
- if type(keepcols) not in [ListType,TupleType,N.ndarray]:
- keepcols = [keepcols]
- if type(collapsecols) not in [ListType,TupleType,N.ndarray]:
- collapsecols = [collapsecols]
-
- if cfcn == None:
- cfcn = acollmean
- if keepcols == []:
- avgcol = acolex(a,collapsecols)
- means = N.sum(avgcol)/float(len(avgcol))
- if fcn1<>None:
- try:
- test = fcn1(avgcol)
- except:
- test = N.array(['N/A']*len(means))
- means = aabut(means,test)
- if fcn2<>None:
- try:
- test = fcn2(avgcol)
- except:
- test = N.array(['N/A']*len(means))
- means = aabut(means,test)
- return means
- else:
- if type(keepcols) not in [ListType,TupleType,N.ndarray]:
- keepcols = [keepcols]
- values = colex(a,keepcols) # so that "item" can be appended (below)
- uniques = unique(values) # get a LIST, so .sort keeps rows intact
- uniques.sort()
- newlist = []
- for item in uniques:
- if type(item) not in [ListType,TupleType,N.ndarray]:
- item =[item]
- tmprows = alinexand(a,keepcols,item)
- for col in collapsecols:
- avgcol = acolex(tmprows,col)
- item.append(acollmean(avgcol))
- if fcn1<>None:
- try:
- test = fcn1(avgcol)
- except:
- test = 'N/A'
- item.append(test)
- if fcn2<>None:
- try:
- test = fcn2(avgcol)
- except:
- test = 'N/A'
- item.append(test)
- newlist.append(item)
- try:
- new_a = N.array(newlist)
- except TypeError:
- new_a = N.array(newlist,'O')
- return new_a
-
-
- def adm (a,criterion):
- """
-Returns rows from the passed list of lists that meet the criteria in
-the passed criterion expression (a string as a function of x).
-
-Usage: adm (a,criterion) where criterion is like 'x[2]==37'
-"""
- function = 'filter(lambda x: '+criterion+',a)'
- lines = eval(function)
- try:
- lines = N.array(lines)
- except:
- lines = N.array(lines,dtype='O')
- return lines
-
-
- def isstring(x):
- if type(x)==StringType:
- return 1
- else:
- return 0
-
-
- def alinexand (a,columnlist,valuelist):
- """
-Returns the rows of an array where col (from columnlist) = val
-(from valuelist). One value is required for each column in columnlist.
-
-Usage: alinexand (a,columnlist,valuelist)
-Returns: the rows of a where columnlist[i]=valuelist[i] for ALL i
-"""
- if type(columnlist) not in [ListType,TupleType,N.ndarray]:
- columnlist = [columnlist]
- if type(valuelist) not in [ListType,TupleType,N.ndarray]:
- valuelist = [valuelist]
- criterion = ''
- for i in range(len(columnlist)):
- if type(valuelist[i])==StringType:
- critval = '\'' + valuelist[i] + '\''
- else:
- critval = str(valuelist[i])
- criterion = criterion + ' x['+str(columnlist[i])+']=='+critval+' and'
- criterion = criterion[0:-3] # remove the "and" after the last crit
- return adm(a,criterion)
-
-
- def alinexor (a,columnlist,valuelist):
- """
-Returns the rows of an array where col (from columnlist) = val (from
-valuelist). One value is required for each column in columnlist.
-The exception is if either columnlist or valuelist has only 1 value,
-in which case that item will be expanded to match the length of the
-other list.
-
-Usage: alinexor (a,columnlist,valuelist)
-Returns: the rows of a where columnlist[i]=valuelist[i] for ANY i
-"""
- if type(columnlist) not in [ListType,TupleType,N.ndarray]:
- columnlist = [columnlist]
- if type(valuelist) not in [ListType,TupleType,N.ndarray]:
- valuelist = [valuelist]
- criterion = ''
- if len(columnlist) == 1 and len(valuelist) > 1:
- columnlist = columnlist*len(valuelist)
- elif len(valuelist) == 1 and len(columnlist) > 1:
- valuelist = valuelist*len(columnlist)
- for i in range(len(columnlist)):
- if type(valuelist[i])==StringType:
- critval = '\'' + valuelist[i] + '\''
- else:
- critval = str(valuelist[i])
- criterion = criterion + ' x['+str(columnlist[i])+']=='+critval+' or'
- criterion = criterion[0:-2] # remove the "or" after the last crit
- return adm(a,criterion)
-
-
- def areplace (a,oldval,newval):
- """
-Replaces all occurrences of oldval with newval in array a.
-
-Usage: areplace(a,oldval,newval)
-"""
- return N.where(a==oldval,newval,a)
-
-
- def arecode (a,listmap,col='all'):
- """
-Remaps the values in an array to a new set of values (useful when
-you need to recode data from (e.g.) strings to numbers as most stats
-packages require. Can work on SINGLE columns, or 'all' columns at once.
-@@@BROKEN 2007-11-26
-
-Usage: arecode (a,listmap,col='all')
-Returns: a version of array a where listmap[i][0] = (instead) listmap[i][1]
-"""
- ashape = a.shape
- if col == 'all':
- work = a.ravel()
- else:
- work = acolex(a,col)
- work = work.ravel()
- for pair in listmap:
- if type(pair[1]) == StringType or work.dtype.char=='O' or a.dtype.char=='O':
- work = N.array(work,dtype='O')
- a = N.array(a,dtype='O')
- for i in range(len(work)):
- if work[i]==pair[0]:
- work[i] = pair[1]
- if col == 'all':
- return N.reshape(work,ashape)
- else:
- return N.concatenate([a[:,0:col],work[:,N.newaxis],a[:,col+1:]],1)
- else: # must be a non-Object type array and replacement
- work = N.where(work==pair[0],pair[1],work)
- return N.concatenate([a[:,0:col],work[:,N.newaxis],a[:,col+1:]],1)
-
-
- def arowcompare(row1, row2):
- """
-Compares two rows from an array, regardless of whether it is an
-array of numbers or of python objects (which requires the cmp function).
-@@@PURPOSE? 2007-11-26
-
-Usage: arowcompare(row1,row2)
-Returns: an array of equal length containing 1s where the two rows had
- identical elements and 0 otherwise
-"""
- return
- if row1.dtype.char=='O' or row2.dtype=='O':
- cmpvect = N.logical_not(abs(N.array(map(cmp,row1,row2)))) # cmp fcn gives -1,0,1
- else:
- cmpvect = N.equal(row1,row2)
- return cmpvect
-
-
- def arowsame(row1, row2):
- """
-Compares two rows from an array, regardless of whether it is an
-array of numbers or of python objects (which requires the cmp function).
-
-Usage: arowsame(row1,row2)
-Returns: 1 if the two rows are identical, 0 otherwise.
-"""
- cmpval = N.alltrue(arowcompare(row1,row2))
- return cmpval
-
-
- def asortrows(a,axis=0):
- """
-Sorts an array "by rows". This differs from the Numeric.sort() function,
-which sorts elements WITHIN the given axis. Instead, this function keeps
-the elements along the given axis intact, but shifts them 'up or down'
-relative to one another.
-
-Usage: asortrows(a,axis=0)
-Returns: sorted version of a
-"""
- return N.sort(a,axis=axis,kind='mergesort')
-
-
- def aunique(inarray):
- """
-Returns unique items in the FIRST dimension of the passed array. Only
-works on arrays NOT including string items.
-
-Usage: aunique (inarray)
-"""
- uniques = N.array([inarray[0]])
- if len(uniques.shape) == 1: # IF IT'S A 1D ARRAY
- for item in inarray[1:]:
- if N.add.reduce(N.equal(uniques,item).ravel()) == 0:
- try:
- uniques = N.concatenate([uniques,N.array[N.newaxis,:]])
- except TypeError:
- uniques = N.concatenate([uniques,N.array([item])])
- else: # IT MUST BE A 2+D ARRAY
- if inarray.dtype.char != 'O': # not an Object array
- for item in inarray[1:]:
- if not N.sum(N.alltrue(N.equal(uniques,item),1)):
- try:
- uniques = N.concatenate( [uniques,item[N.newaxis,:]] )
- except TypeError: # the item to add isn't a list
- uniques = N.concatenate([uniques,N.array([item])])
- else:
- pass # this item is already in the uniques array
- else: # must be an Object array, alltrue/equal functions don't work
- for item in inarray[1:]:
- newflag = 1
- for unq in uniques: # NOTE: cmp --> 0=same, -1=<, 1=>
- test = N.sum(abs(N.array(map(cmp,item,unq))))
- if test == 0: # if item identical to any 1 row in uniques
- newflag = 0 # then not a novel item to add
- break
- if newflag == 1:
- try:
- uniques = N.concatenate( [uniques,item[N.newaxis,:]] )
- except TypeError: # the item to add isn't a list
- uniques = N.concatenate([uniques,N.array([item])])
- return uniques
-
-
- def aduplicates(inarray):
- """
-Returns duplicate items in the FIRST dimension of the passed array. Only
-works on arrays NOT including string items.
-
-Usage: aunique (inarray)
-"""
- inarray = N.array(inarray)
- if len(inarray.shape) == 1: # IF IT'S A 1D ARRAY
- dups = []
- inarray = inarray.tolist()
- for i in range(len(inarray)):
- if inarray[i] in inarray[i+1:]:
- dups.append(inarray[i])
- dups = aunique(dups)
- else: # IT MUST BE A 2+D ARRAY
- dups = []
- aslist = inarray.tolist()
- for i in range(len(aslist)):
- if aslist[i] in aslist[i+1:]:
- dups.append(aslist[i])
- dups = unique(dups)
- dups = N.array(dups)
- return dups
-
-except ImportError: # IF NUMERIC ISN'T AVAILABLE, SKIP ALL arrayfuncs
- pass
diff --git a/v14/utils/stats.py b/v14/utils/stats.py
deleted file mode 100644
index aceed824..00000000
--- a/v14/utils/stats.py
+++ /dev/null
@@ -1,4528 +0,0 @@
-# Copyright (c) 1999-2008 Gary Strangman; All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-# Comments and/or additions are welcome (send e-mail to:
-# strang@nmr.mgh.harvard.edu).
-#
-"""
-stats.py module
-
-(Requires pstat.py module.)
-
-#################################################
-####### Written by: Gary Strangman ###########
-####### Last modified: Oct 31, 2008 ###########
-#################################################
-
-A collection of basic statistical functions for python. The function
-names appear below.
-
-IMPORTANT: There are really *3* sets of functions. The first set has an 'l'
-prefix, which can be used with list or tuple arguments. The second set has
-an 'a' prefix, which can accept NumPy array arguments. These latter
-functions are defined only when NumPy is available on the system. The third
-type has NO prefix (i.e., has the name that appears below). Functions of
-this set are members of a "Dispatch" class, c/o David Ascher. This class
-allows different functions to be called depending on the type of the passed
-arguments. Thus, stats.mean is a member of the Dispatch class and
-stats.mean(range(20)) will call stats.lmean(range(20)) while
-stats.mean(Numeric.arange(20)) will call stats.amean(Numeric.arange(20)).
-This is a handy way to keep consistent function names when different
-argument types require different functions to be called. Having
-implementated the Dispatch class, however, means that to get info on
-a given function, you must use the REAL function name ... that is
-"print stats.lmean.__doc__" or "print stats.amean.__doc__" work fine,
-while "print stats.mean.__doc__" will print the doc for the Dispatch
-class. NUMPY FUNCTIONS ('a' prefix) generally have more argument options
-but should otherwise be consistent with the corresponding list functions.
-
-Disclaimers: The function list is obviously incomplete and, worse, the
-functions are not optimized. All functions have been tested (some more
-so than others), but they are far from bulletproof. Thus, as with any
-free software, no warranty or guarantee is expressed or implied. :-) A
-few extra functions that don't appear in the list below can be found by
-interested treasure-hunters. These functions don't necessarily have
-both list and array versions but were deemed useful
-
-CENTRAL TENDENCY: geometricmean
- harmonicmean
- mean
- median
- medianscore
- mode
-
-MOMENTS: moment
- variation
- skew
- kurtosis
- skewtest (for Numpy arrays only)
- kurtosistest (for Numpy arrays only)
- normaltest (for Numpy arrays only)
-
-ALTERED VERSIONS: tmean (for Numpy arrays only)
- tvar (for Numpy arrays only)
- tmin (for Numpy arrays only)
- tmax (for Numpy arrays only)
- tstdev (for Numpy arrays only)
- tsem (for Numpy arrays only)
- describe
-
-FREQUENCY STATS: itemfreq
- scoreatpercentile
- percentileofscore
- histogram
- cumfreq
- relfreq
-
-VARIABILITY: obrientransform
- samplevar
- samplestdev
- signaltonoise (for Numpy arrays only)
- var
- stdev
- sterr
- sem
- z
- zs
- zmap (for Numpy arrays only)
-
-TRIMMING FCNS: threshold (for Numpy arrays only)
- trimboth
- trim1
- round (round all vals to 'n' decimals; Numpy only)
-
-CORRELATION FCNS: covariance (for Numpy arrays only)
- correlation (for Numpy arrays only)
- paired
- pearsonr
- spearmanr
- pointbiserialr
- kendalltau
- linregress
-
-INFERENTIAL STATS: ttest_1samp
- ttest_ind
- ttest_rel
- chisquare
- ks_2samp
- mannwhitneyu
- ranksums
- wilcoxont
- kruskalwallish
- friedmanchisquare
-
-PROBABILITY CALCS: chisqprob
- erfcc
- zprob
- ksprob
- fprob
- betacf
- gammln
- betai
-
-ANOVA FUNCTIONS: F_oneway
- F_value
-
-SUPPORT FUNCTIONS: writecc
- incr
- sign (for Numpy arrays only)
- sum
- cumsum
- ss
- summult
- sumdiffsquared
- square_of_sums
- shellsort
- rankdata
- outputpairedstats
- findwithin
-"""
-## CHANGE LOG:
-## ===========
-## 09-07-21 ... added capability for getting the 'proportion' out of l/amannwhitneyu (but comment-disabled)
-## 08-10-31 ... fixed import LinearAlgebra bug before glm fcns
-## 07-11-26 ... conversion for numpy started
-## 07-05-16 ... added Lin's Concordance Correlation Coefficient (alincc) and acov
-## 05-08-21 ... added "Dice's coefficient"
-## 04-10-26 ... added ap2t(), an ugly fcn for converting p-vals to T-vals
-## 04-04-03 ... added amasslinregress() function to do regression on N-D arrays
-## 03-01-03 ... CHANGED VERSION TO 0.6
-## fixed atsem() to properly handle limits=None case
-## improved histogram and median functions (estbinwidth) and
-## fixed atvar() function (wrong answers for neg numbers?!?)
-## 02-11-19 ... fixed attest_ind and attest_rel for div-by-zero Overflows
-## 02-05-10 ... fixed lchisqprob indentation (failed when df=even)
-## 00-12-28 ... removed aanova() to separate module, fixed licensing to
-## match Python License, fixed doc string & imports
-## 00-04-13 ... pulled all "global" statements, except from aanova()
-## added/fixed lots of documentation, removed io.py dependency
-## changed to version 0.5
-## 99-11-13 ... added asign() function
-## 99-11-01 ... changed version to 0.4 ... enough incremental changes now
-## 99-10-25 ... added acovariance and acorrelation functions
-## 99-10-10 ... fixed askew/akurtosis to avoid divide-by-zero errors
-## added aglm function (crude, but will be improved)
-## 99-10-04 ... upgraded acumsum, ass, asummult, asamplevar, avar, etc. to
-## all handle lists of 'dimension's and keepdims
-## REMOVED ar0, ar2, ar3, ar4 and replaced them with around
-## reinserted fixes for abetai to avoid math overflows
-## 99-09-05 ... rewrote achisqprob/aerfcc/aksprob/afprob/abetacf/abetai to
-## handle multi-dimensional arrays (whew!)
-## 99-08-30 ... fixed l/amoment, l/askew, l/akurtosis per D'Agostino (1990)
-## added anormaltest per same reference
-## re-wrote azprob to calc arrays of probs all at once
-## 99-08-22 ... edited attest_ind printing section so arrays could be rounded
-## 99-08-19 ... fixed amean and aharmonicmean for non-error(!) overflow on
-## short/byte arrays (mean of #s btw 100-300 = -150??)
-## 99-08-09 ... fixed asum so that the None case works for Byte arrays
-## 99-08-08 ... fixed 7/3 'improvement' to handle t-calcs on N-D arrays
-## 99-07-03 ... improved attest_ind, attest_rel (zero-division errortrap)
-## 99-06-24 ... fixed bug(?) in attest_ind (n1=a.shape[0])
-## 04/11/99 ... added asignaltonoise, athreshold functions, changed all
-## max/min in array section to N.maximum/N.minimum,
-## fixed square_of_sums to prevent integer overflow
-## 04/10/99 ... !!! Changed function name ... sumsquared ==> square_of_sums
-## 03/18/99 ... Added ar0, ar2, ar3 and ar4 rounding functions
-## 02/28/99 ... Fixed aobrientransform to return an array rather than a list
-## 01/15/99 ... Essentially ceased updating list-versions of functions (!!!)
-## 01/13/99 ... CHANGED TO VERSION 0.3
-## fixed bug in a/lmannwhitneyu p-value calculation
-## 12/31/98 ... fixed variable-name bug in ldescribe
-## 12/19/98 ... fixed bug in findwithin (fcns needed pstat. prefix)
-## 12/16/98 ... changed amedianscore to return float (not array) for 1 score
-## 12/14/98 ... added atmin and atmax functions
-## removed umath from import line (not needed)
-## l/ageometricmean modified to reduce chance of overflows (take
-## nth root first, then multiply)
-## 12/07/98 ... added __version__variable (now 0.2)
-## removed all 'stats.' from anova() fcn
-## 12/06/98 ... changed those functions (except shellsort) that altered
-## arguments in-place ... cumsum, ranksort, ...
-## updated (and fixed some) doc-strings
-## 12/01/98 ... added anova() function (requires NumPy)
-## incorporated Dispatch class
-## 11/12/98 ... added functionality to amean, aharmonicmean, ageometricmean
-## added 'asum' function (added functionality to N.add.reduce)
-## fixed both moment and amoment (two errors)
-## changed name of skewness and askewness to skew and askew
-## fixed (a)histogram (which sometimes counted points <lowerlimit)
-
-import pstat # required 3rd party module
-import math, string, copy # required python modules
-from types import *
-
-__version__ = 0.6
-
-############# DISPATCH CODE ##############
-
-
-class Dispatch:
- """
-The Dispatch class, care of David Ascher, allows different functions to
-be called depending on the argument types. This way, there can be one
-function name regardless of the argument type. To access function doc
-in stats.py module, prefix the function with an 'l' or 'a' for list or
-array arguments, respectively. That is, print stats.lmean.__doc__ or
-print stats.amean.__doc__ or whatever.
-"""
-
- def __init__(self, *tuples):
- self._dispatch = {}
- for func, types in tuples:
- for t in types:
- if t in self._dispatch.keys():
- raise ValueError, "can't have two dispatches on "+str(t)
- self._dispatch[t] = func
- self._types = self._dispatch.keys()
-
- def __call__(self, arg1, *args, **kw):
- if type(arg1) not in self._types:
- raise TypeError, "don't know how to dispatch %s arguments" % type(arg1)
- return apply(self._dispatch[type(arg1)], (arg1,) + args, kw)
-
-
-##########################################################################
-######################## LIST-BASED FUNCTIONS ########################
-##########################################################################
-
-### Define these regardless
-
-####################################
-####### CENTRAL TENDENCY #########
-####################################
-
-def lgeometricmean (inlist):
- """
-Calculates the geometric mean of the values in the passed list.
-That is: n-th root of (x1 * x2 * ... * xn). Assumes a '1D' list.
-
-Usage: lgeometricmean(inlist)
-"""
- mult = 1.0
- one_over_n = 1.0/len(inlist)
- for item in inlist:
- mult = mult * pow(item,one_over_n)
- return mult
-
-
-def lharmonicmean (inlist):
- """
-Calculates the harmonic mean of the values in the passed list.
-That is: n / (1/x1 + 1/x2 + ... + 1/xn). Assumes a '1D' list.
-
-Usage: lharmonicmean(inlist)
-"""
- sum = 0
- for item in inlist:
- sum = sum + 1.0/item
- return len(inlist) / sum
-
-
-def lmean (inlist):
- """
-Returns the arithematic mean of the values in the passed list.
-Assumes a '1D' list, but will function on the 1st dim of an array(!).
-
-Usage: lmean(inlist)
-"""
- sum = 0
- for item in inlist:
- sum = sum + item
- return sum/float(len(inlist))
-
-
-def lmedian (inlist,numbins=1000):
- """
-Returns the computed median value of a list of numbers, given the
-number of bins to use for the histogram (more bins brings the computed value
-closer to the median score, default number of bins = 1000). See G.W.
-Heiman's Basic Stats (1st Edition), or CRC Probability & Statistics.
-
-Usage: lmedian (inlist, numbins=1000)
-"""
- (hist, smallest, binsize, extras) = histogram(inlist,numbins,[min(inlist),max(inlist)]) # make histog
- cumhist = cumsum(hist) # make cumulative histogram
- for i in range(len(cumhist)): # get 1st(!) index holding 50%ile score
- if cumhist[i]>=len(inlist)/2.0:
- cfbin = i
- break
- LRL = smallest + binsize*cfbin # get lower read limit of that bin
- cfbelow = cumhist[cfbin-1]
- freq = float(hist[cfbin]) # frequency IN the 50%ile bin
- median = LRL + ((len(inlist)/2.0 - cfbelow)/float(freq))*binsize # median formula
- return median
-
-
-def lmedianscore (inlist):
- """
-Returns the 'middle' score of the passed list. If there is an even
-number of scores, the mean of the 2 middle scores is returned.
-
-Usage: lmedianscore(inlist)
-"""
-
- newlist = copy.deepcopy(inlist)
- newlist.sort()
- if len(newlist) % 2 == 0: # if even number of scores, average middle 2
- index = len(newlist)/2 # integer division correct
- median = float(newlist[index] + newlist[index-1]) /2
- else:
- index = len(newlist)/2 # int divsion gives mid value when count from 0
- median = newlist[index]
- return median
-
-
-def lmode(inlist):
- """
-Returns a list of the modal (most common) score(s) in the passed
-list. If there is more than one such score, all are returned. The
-bin-count for the mode(s) is also returned.
-
-Usage: lmode(inlist)
-Returns: bin-count for mode(s), a list of modal value(s)
-"""
-
- scores = pstat.unique(inlist)
- scores.sort()
- freq = []
- for item in scores:
- freq.append(inlist.count(item))
- maxfreq = max(freq)
- mode = []
- stillmore = 1
- while stillmore:
- try:
- indx = freq.index(maxfreq)
- mode.append(scores[indx])
- del freq[indx]
- del scores[indx]
- except ValueError:
- stillmore=0
- return maxfreq, mode
-
-
-####################################
-############ MOMENTS #############
-####################################
-
-def lmoment(inlist,moment=1):
- """
-Calculates the nth moment about the mean for a sample (defaults to
-the 1st moment). Used to calculate coefficients of skewness and kurtosis.
-
-Usage: lmoment(inlist,moment=1)
-Returns: appropriate moment (r) from ... 1/n * SUM((inlist(i)-mean)**r)
-"""
- if moment == 1:
- return 0.0
- else:
- mn = mean(inlist)
- n = len(inlist)
- s = 0
- for x in inlist:
- s = s + (x-mn)**moment
- return s/float(n)
-
-
-def lvariation(inlist):
- """
-Returns the coefficient of variation, as defined in CRC Standard
-Probability and Statistics, p.6.
-
-Usage: lvariation(inlist)
-"""
- return 100.0*samplestdev(inlist)/float(mean(inlist))
-
-
-def lskew(inlist):
- """
-Returns the skewness of a distribution, as defined in Numerical
-Recipies (alternate defn in CRC Standard Probability and Statistics, p.6.)
-
-Usage: lskew(inlist)
-"""
- return moment(inlist,3)/pow(moment(inlist,2),1.5)
-
-
-def lkurtosis(inlist):
- """
-Returns the kurtosis of a distribution, as defined in Numerical
-Recipies (alternate defn in CRC Standard Probability and Statistics, p.6.)
-
-Usage: lkurtosis(inlist)
-"""
- return moment(inlist,4)/pow(moment(inlist,2),2.0)
-
-
-def ldescribe(inlist):
- """
-Returns some descriptive statistics of the passed list (assumed to be 1D).
-
-Usage: ldescribe(inlist)
-Returns: n, mean, standard deviation, skew, kurtosis
-"""
- n = len(inlist)
- mm = (min(inlist),max(inlist))
- m = mean(inlist)
- sd = stdev(inlist)
- sk = skew(inlist)
- kurt = kurtosis(inlist)
- return n, mm, m, sd, sk, kurt
-
-
-####################################
-####### FREQUENCY STATS ##########
-####################################
-
-def litemfreq(inlist):
- """
-Returns a list of pairs. Each pair consists of one of the scores in inlist
-and it's frequency count. Assumes a 1D list is passed.
-
-Usage: litemfreq(inlist)
-Returns: a 2D frequency table (col [0:n-1]=scores, col n=frequencies)
-"""
- scores = pstat.unique(inlist)
- scores.sort()
- freq = []
- for item in scores:
- freq.append(inlist.count(item))
- return pstat.abut(scores, freq)
-
-
-def lscoreatpercentile (inlist, percent):
- """
-Returns the score at a given percentile relative to the distribution
-given by inlist.
-
-Usage: lscoreatpercentile(inlist,percent)
-"""
- if percent > 1:
- print "\nDividing percent>1 by 100 in lscoreatpercentile().\n"
- percent = percent / 100.0
- targetcf = percent*len(inlist)
- h, lrl, binsize, extras = histogram(inlist)
- cumhist = cumsum(copy.deepcopy(h))
- for i in range(len(cumhist)):
- if cumhist[i] >= targetcf:
- break
- score = binsize * ((targetcf - cumhist[i-1]) / float(h[i])) + (lrl+binsize*i)
- return score
-
-
-def lpercentileofscore (inlist, score,histbins=10,defaultlimits=None):
- """
-Returns the percentile value of a score relative to the distribution
-given by inlist. Formula depends on the values used to histogram the data(!).
-
-Usage: lpercentileofscore(inlist,score,histbins=10,defaultlimits=None)
-"""
-
- h, lrl, binsize, extras = histogram(inlist,histbins,defaultlimits)
- cumhist = cumsum(copy.deepcopy(h))
- i = int((score - lrl)/float(binsize))
- pct = (cumhist[i-1]+((score-(lrl+binsize*i))/float(binsize))*h[i])/float(len(inlist)) * 100
- return pct
-
-
-def lhistogram (inlist,numbins=10,defaultreallimits=None,printextras=0):
- """
-Returns (i) a list of histogram bin counts, (ii) the smallest value
-of the histogram binning, and (iii) the bin width (the last 2 are not
-necessarily integers). Default number of bins is 10. If no sequence object
-is given for defaultreallimits, the routine picks (usually non-pretty) bins
-spanning all the numbers in the inlist.
-
-Usage: lhistogram (inlist, numbins=10, defaultreallimits=None,suppressoutput=0)
-Returns: list of bin values, lowerreallimit, binsize, extrapoints
-"""
- if (defaultreallimits <> None):
- if type(defaultreallimits) not in [ListType,TupleType] or len(defaultreallimits)==1: # only one limit given, assumed to be lower one & upper is calc'd
- lowerreallimit = defaultreallimits
- upperreallimit = 1.000001 * max(inlist)
- else: # assume both limits given
- lowerreallimit = defaultreallimits[0]
- upperreallimit = defaultreallimits[1]
- binsize = (upperreallimit-lowerreallimit)/float(numbins)
- else: # no limits given for histogram, both must be calc'd
- estbinwidth=(max(inlist)-min(inlist))/float(numbins) +1e-6 #1=>cover all
- binsize = ((max(inlist)-min(inlist)+estbinwidth))/float(numbins)
- lowerreallimit = min(inlist) - binsize/2 #lower real limit,1st bin
- bins = [0]*(numbins)
- extrapoints = 0
- for num in inlist:
- try:
- if (num-lowerreallimit) < 0:
- extrapoints = extrapoints + 1
- else:
- bintoincrement = int((num-lowerreallimit)/float(binsize))
- bins[bintoincrement] = bins[bintoincrement] + 1
- except:
- extrapoints = extrapoints + 1
- if (extrapoints > 0 and printextras == 1):
- print '\nPoints outside given histogram range =',extrapoints
- return (bins, lowerreallimit, binsize, extrapoints)
-
-
-def lcumfreq(inlist,numbins=10,defaultreallimits=None):
- """
-Returns a cumulative frequency histogram, using the histogram function.
-
-Usage: lcumfreq(inlist,numbins=10,defaultreallimits=None)
-Returns: list of cumfreq bin values, lowerreallimit, binsize, extrapoints
-"""
- h,l,b,e = histogram(inlist,numbins,defaultreallimits)
- cumhist = cumsum(copy.deepcopy(h))
- return cumhist,l,b,e
-
-
-def lrelfreq(inlist,numbins=10,defaultreallimits=None):
- """
-Returns a relative frequency histogram, using the histogram function.
-
-Usage: lrelfreq(inlist,numbins=10,defaultreallimits=None)
-Returns: list of cumfreq bin values, lowerreallimit, binsize, extrapoints
-"""
- h,l,b,e = histogram(inlist,numbins,defaultreallimits)
- for i in range(len(h)):
- h[i] = h[i]/float(len(inlist))
- return h,l,b,e
-
-
-####################################
-##### VARIABILITY FUNCTIONS ######
-####################################
-
-def lobrientransform(*args):
- """
-Computes a transform on input data (any number of columns). Used to
-test for homogeneity of variance prior to running one-way stats. From
-Maxwell and Delaney, p.112.
-
-Usage: lobrientransform(*args)
-Returns: transformed data for use in an ANOVA
-"""
- TINY = 1e-10
- k = len(args)
- n = [0.0]*k
- v = [0.0]*k
- m = [0.0]*k
- nargs = []
- for i in range(k):
- nargs.append(copy.deepcopy(args[i]))
- n[i] = float(len(nargs[i]))
- v[i] = var(nargs[i])
- m[i] = mean(nargs[i])
- for j in range(k):
- for i in range(n[j]):
- t1 = (n[j]-1.5)*n[j]*(nargs[j][i]-m[j])**2
- t2 = 0.5*v[j]*(n[j]-1.0)
- t3 = (n[j]-1.0)*(n[j]-2.0)
- nargs[j][i] = (t1-t2) / float(t3)
- check = 1
- for j in range(k):
- if v[j] - mean(nargs[j]) > TINY:
- check = 0
- if check <> 1:
- raise ValueError, 'Problem in obrientransform.'
- else:
- return nargs
-
-
-def lsamplevar (inlist):
- """
-Returns the variance of the values in the passed list using
-N for the denominator (i.e., DESCRIBES the sample variance only).
-
-Usage: lsamplevar(inlist)
-"""
- n = len(inlist)
- mn = mean(inlist)
- deviations = []
- for item in inlist:
- deviations.append(item-mn)
- return ss(deviations)/float(n)
-
-
-def lsamplestdev (inlist):
- """
-Returns the standard deviation of the values in the passed list using
-N for the denominator (i.e., DESCRIBES the sample stdev only).
-
-Usage: lsamplestdev(inlist)
-"""
- return math.sqrt(samplevar(inlist))
-
-
-def lcov (x,y, keepdims=0):
- """
-Returns the estimated covariance of the values in the passed
-array (i.e., N-1). Dimension can equal None (ravel array first), an
-integer (the dimension over which to operate), or a sequence (operate
-over multiple dimensions). Set keepdims=1 to return an array with the
-same number of dimensions as inarray.
-
-Usage: lcov(x,y,keepdims=0)
-"""
-
- n = len(x)
- xmn = mean(x)
- ymn = mean(y)
- xdeviations = [0]*len(x)
- ydeviations = [0]*len(y)
- for i in range(len(x)):
- xdeviations[i] = x[i] - xmn
- ydeviations[i] = y[i] - ymn
- ss = 0.0
- for i in range(len(xdeviations)):
- ss = ss + xdeviations[i]*ydeviations[i]
- return ss/float(n-1)
-
-
-def lvar (inlist):
- """
-Returns the variance of the values in the passed list using N-1
-for the denominator (i.e., for estimating population variance).
-
-Usage: lvar(inlist)
-"""
- n = len(inlist)
- mn = mean(inlist)
- deviations = [0]*len(inlist)
- for i in range(len(inlist)):
- deviations[i] = inlist[i] - mn
- return ss(deviations)/float(n-1)
-
-
-def lstdev (inlist):
- """
-Returns the standard deviation of the values in the passed list
-using N-1 in the denominator (i.e., to estimate population stdev).
-
-Usage: lstdev(inlist)
-"""
- return math.sqrt(var(inlist))
-
-
-def lsterr(inlist):
- """
-Returns the standard error of the values in the passed list using N-1
-in the denominator (i.e., to estimate population standard error).
-
-Usage: lsterr(inlist)
-"""
- return stdev(inlist) / float(math.sqrt(len(inlist)))
-
-
-def lsem (inlist):
- """
-Returns the estimated standard error of the mean (sx-bar) of the
-values in the passed list. sem = stdev / sqrt(n)
-
-Usage: lsem(inlist)
-"""
- sd = stdev(inlist)
- n = len(inlist)
- return sd/math.sqrt(n)
-
-
-def lz (inlist, score):
- """
-Returns the z-score for a given input score, given that score and the
-list from which that score came. Not appropriate for population calculations.
-
-Usage: lz(inlist, score)
-"""
- z = (score-mean(inlist))/samplestdev(inlist)
- return z
-
-
-def lzs (inlist):
- """
-Returns a list of z-scores, one for each score in the passed list.
-
-Usage: lzs(inlist)
-"""
- zscores = []
- for item in inlist:
- zscores.append(z(inlist,item))
- return zscores
-
-
-####################################
-####### TRIMMING FUNCTIONS #######
-####################################
-
-def ltrimboth (l,proportiontocut):
- """
-Slices off the passed proportion of items from BOTH ends of the passed
-list (i.e., with proportiontocut=0.1, slices 'leftmost' 10% AND 'rightmost'
-10% of scores. Assumes list is sorted by magnitude. Slices off LESS if
-proportion results in a non-integer slice index (i.e., conservatively
-slices off proportiontocut).
-
-Usage: ltrimboth (l,proportiontocut)
-Returns: trimmed version of list l
-"""
- lowercut = int(proportiontocut*len(l))
- uppercut = len(l) - lowercut
- return l[lowercut:uppercut]
-
-
-def ltrim1 (l,proportiontocut,tail='right'):
- """
-Slices off the passed proportion of items from ONE end of the passed
-list (i.e., if proportiontocut=0.1, slices off 'leftmost' or 'rightmost'
-10% of scores). Slices off LESS if proportion results in a non-integer
-slice index (i.e., conservatively slices off proportiontocut).
-
-Usage: ltrim1 (l,proportiontocut,tail='right') or set tail='left'
-Returns: trimmed version of list l
-"""
- if tail == 'right':
- lowercut = 0
- uppercut = len(l) - int(proportiontocut*len(l))
- elif tail == 'left':
- lowercut = int(proportiontocut*len(l))
- uppercut = len(l)
- return l[lowercut:uppercut]
-
-
-####################################
-##### CORRELATION FUNCTIONS ######
-####################################
-
-def lpaired(x,y):
- """
-Interactively determines the type of data and then runs the
-appropriated statistic for paired group data.
-
-Usage: lpaired(x,y)
-Returns: appropriate statistic name, value, and probability
-"""
- samples = ''
- while samples not in ['i','r','I','R','c','C']:
- print '\nIndependent or related samples, or correlation (i,r,c): ',
- samples = raw_input()
-
- if samples in ['i','I','r','R']:
- print '\nComparing variances ...',
-# USE O'BRIEN'S TEST FOR HOMOGENEITY OF VARIANCE, Maxwell & delaney, p.112
- r = obrientransform(x,y)
- f,p = F_oneway(pstat.colex(r,0),pstat.colex(r,1))
- if p<0.05:
- vartype='unequal, p='+str(round(p,4))
- else:
- vartype='equal'
- print vartype
- if samples in ['i','I']:
- if vartype[0]=='e':
- t,p = ttest_ind(x,y,0)
- print '\nIndependent samples t-test: ', round(t,4),round(p,4)
- else:
- if len(x)>20 or len(y)>20:
- z,p = ranksums(x,y)
- print '\nRank Sums test (NONparametric, n>20): ', round(z,4),round(p,4)
- else:
- u,p = mannwhitneyu(x,y)
- print '\nMann-Whitney U-test (NONparametric, ns<20): ', round(u,4),round(p,4)
-
- else: # RELATED SAMPLES
- if vartype[0]=='e':
- t,p = ttest_rel(x,y,0)
- print '\nRelated samples t-test: ', round(t,4),round(p,4)
- else:
- t,p = ranksums(x,y)
- print '\nWilcoxon T-test (NONparametric): ', round(t,4),round(p,4)
- else: # CORRELATION ANALYSIS
- corrtype = ''
- while corrtype not in ['c','C','r','R','d','D']:
- print '\nIs the data Continuous, Ranked, or Dichotomous (c,r,d): ',
- corrtype = raw_input()
- if corrtype in ['c','C']:
- m,b,r,p,see = linregress(x,y)
- print '\nLinear regression for continuous variables ...'
- lol = [['Slope','Intercept','r','Prob','SEestimate'],[round(m,4),round(b,4),round(r,4),round(p,4),round(see,4)]]
- pstat.printcc(lol)
- elif corrtype in ['r','R']:
- r,p = spearmanr(x,y)
- print '\nCorrelation for ranked variables ...'
- print "Spearman's r: ",round(r,4),round(p,4)
- else: # DICHOTOMOUS
- r,p = pointbiserialr(x,y)
- print '\nAssuming x contains a dichotomous variable ...'
- print 'Point Biserial r: ',round(r,4),round(p,4)
- print '\n\n'
- return None
-
-
-def lpearsonr(x,y):
- """
-Calculates a Pearson correlation coefficient and the associated
-probability value. Taken from Heiman's Basic Statistics for the Behav.
-Sci (2nd), p.195.
-
-Usage: lpearsonr(x,y) where x and y are equal-length lists
-Returns: Pearson's r value, two-tailed p-value
-"""
- TINY = 1.0e-30
- if len(x) <> len(y):
- raise ValueError, 'Input values not paired in pearsonr. Aborting.'
- n = len(x)
- x = map(float,x)
- y = map(float,y)
- xmean = mean(x)
- ymean = mean(y)
- r_num = n*(summult(x,y)) - sum(x)*sum(y)
- r_den = math.sqrt((n*ss(x) - square_of_sums(x))*(n*ss(y)-square_of_sums(y)))
- r = (r_num / r_den) # denominator already a float
- df = n-2
- t = r*math.sqrt(df/((1.0-r+TINY)*(1.0+r+TINY)))
- prob = betai(0.5*df,0.5,df/float(df+t*t))
- return r, prob
-
-
-def llincc(x,y):
- """
-Calculates Lin's concordance correlation coefficient.
-
-Usage: alincc(x,y) where x, y are equal-length arrays
-Returns: Lin's CC
-"""
- covar = lcov(x,y)*(len(x)-1)/float(len(x)) # correct denom to n
- xvar = lvar(x)*(len(x)-1)/float(len(x)) # correct denom to n
- yvar = lvar(y)*(len(y)-1)/float(len(y)) # correct denom to n
- lincc = (2 * covar) / ((xvar+yvar) +((amean(x)-amean(y))**2))
- return lincc
-
-
-def lspearmanr(x,y):
- """
-Calculates a Spearman rank-order correlation coefficient. Taken
-from Heiman's Basic Statistics for the Behav. Sci (1st), p.192.
-
-Usage: lspearmanr(x,y) where x and y are equal-length lists
-Returns: Spearman's r, two-tailed p-value
-"""
- TINY = 1e-30
- if len(x) <> len(y):
- raise ValueError, 'Input values not paired in spearmanr. Aborting.'
- n = len(x)
- rankx = rankdata(x)
- ranky = rankdata(y)
- dsq = sumdiffsquared(rankx,ranky)
- rs = 1 - 6*dsq / float(n*(n**2-1))
- t = rs * math.sqrt((n-2) / ((rs+1.0)*(1.0-rs)))
- df = n-2
- probrs = betai(0.5*df,0.5,df/(df+t*t)) # t already a float
-# probability values for rs are from part 2 of the spearman function in
-# Numerical Recipies, p.510. They are close to tables, but not exact. (?)
- return rs, probrs
-
-
-def lpointbiserialr(x,y):
- """
-Calculates a point-biserial correlation coefficient and the associated
-probability value. Taken from Heiman's Basic Statistics for the Behav.
-Sci (1st), p.194.
-
-Usage: lpointbiserialr(x,y) where x,y are equal-length lists
-Returns: Point-biserial r, two-tailed p-value
-"""
- TINY = 1e-30
- if len(x) <> len(y):
- raise ValueError, 'INPUT VALUES NOT PAIRED IN pointbiserialr. ABORTING.'
- data = pstat.abut(x,y)
- categories = pstat.unique(x)
- if len(categories) <> 2:
- raise ValueError, "Exactly 2 categories required for pointbiserialr()."
- else: # there are 2 categories, continue
- codemap = pstat.abut(categories,range(2))
- recoded = pstat.recode(data,codemap,0)
- x = pstat.linexand(data,0,categories[0])
- y = pstat.linexand(data,0,categories[1])
- xmean = mean(pstat.colex(x,1))
- ymean = mean(pstat.colex(y,1))
- n = len(data)
- adjust = math.sqrt((len(x)/float(n))*(len(y)/float(n)))
- rpb = (ymean - xmean)/samplestdev(pstat.colex(data,1))*adjust
- df = n-2
- t = rpb*math.sqrt(df/((1.0-rpb+TINY)*(1.0+rpb+TINY)))
- prob = betai(0.5*df,0.5,df/(df+t*t)) # t already a float
- return rpb, prob
-
-
-def lkendalltau(x,y):
- """
-Calculates Kendall's tau ... correlation of ordinal data. Adapted
-from function kendl1 in Numerical Recipies. Needs good test-routine.@@@
-
-Usage: lkendalltau(x,y)
-Returns: Kendall's tau, two-tailed p-value
-"""
- n1 = 0
- n2 = 0
- iss = 0
- for j in range(len(x)-1):
- for k in range(j,len(y)):
- a1 = x[j] - x[k]
- a2 = y[j] - y[k]
- aa = a1 * a2
- if (aa): # neither list has a tie
- n1 = n1 + 1
- n2 = n2 + 1
- if aa > 0:
- iss = iss + 1
- else:
- iss = iss -1
- else:
- if (a1):
- n1 = n1 + 1
- else:
- n2 = n2 + 1
- tau = iss / math.sqrt(n1*n2)
- svar = (4.0*len(x)+10.0) / (9.0*len(x)*(len(x)-1))
- z = tau / math.sqrt(svar)
- prob = erfcc(abs(z)/1.4142136)
- return tau, prob
-
-
-def llinregress(x,y):
- """
-Calculates a regression line on x,y pairs.
-
-Usage: llinregress(x,y) x,y are equal-length lists of x-y coordinates
-Returns: slope, intercept, r, two-tailed prob, sterr-of-estimate
-"""
- TINY = 1.0e-20
- if len(x) <> len(y):
- raise ValueError, 'Input values not paired in linregress. Aborting.'
- n = len(x)
- x = map(float,x)
- y = map(float,y)
- xmean = mean(x)
- ymean = mean(y)
- r_num = float(n*(summult(x,y)) - sum(x)*sum(y))
- r_den = math.sqrt((n*ss(x) - square_of_sums(x))*(n*ss(y)-square_of_sums(y)))
- r = r_num / r_den
- z = 0.5*math.log((1.0+r+TINY)/(1.0-r+TINY))
- df = n-2
- t = r*math.sqrt(df/((1.0-r+TINY)*(1.0+r+TINY)))
- prob = betai(0.5*df,0.5,df/(df+t*t))
- slope = r_num / float(n*ss(x) - square_of_sums(x))
- intercept = ymean - slope*xmean
- sterrest = math.sqrt(1-r*r)*samplestdev(y)
- return slope, intercept, r, prob, sterrest
-
-
-####################################
-##### INFERENTIAL STATISTICS #####
-####################################
-
-def lttest_1samp(a,popmean,printit=0,name='Sample',writemode='a'):
- """
-Calculates the t-obtained for the independent samples T-test on ONE group
-of scores a, given a population mean. If printit=1, results are printed
-to the screen. If printit='filename', the results are output to 'filename'
-using the given writemode (default=append). Returns t-value, and prob.
-
-Usage: lttest_1samp(a,popmean,Name='Sample',printit=0,writemode='a')
-Returns: t-value, two-tailed prob
-"""
- x = mean(a)
- v = var(a)
- n = len(a)
- df = n-1
- svar = ((n-1)*v)/float(df)
- t = (x-popmean)/math.sqrt(svar*(1.0/n))
- prob = betai(0.5*df,0.5,float(df)/(df+t*t))
-
- if printit <> 0:
- statname = 'Single-sample T-test.'
- outputpairedstats(printit,writemode,
- 'Population','--',popmean,0,0,0,
- name,n,x,v,min(a),max(a),
- statname,t,prob)
- return t,prob
-
-
-def lttest_ind (a, b, printit=0, name1='Samp1', name2='Samp2', writemode='a'):
- """
-Calculates the t-obtained T-test on TWO INDEPENDENT samples of
-scores a, and b. From Numerical Recipies, p.483. If printit=1, results
-are printed to the screen. If printit='filename', the results are output
-to 'filename' using the given writemode (default=append). Returns t-value,
-and prob.
-
-Usage: lttest_ind(a,b,printit=0,name1='Samp1',name2='Samp2',writemode='a')
-Returns: t-value, two-tailed prob
-"""
- x1 = mean(a)
- x2 = mean(b)
- v1 = stdev(a)**2
- v2 = stdev(b)**2
- n1 = len(a)
- n2 = len(b)
- df = n1+n2-2
- svar = ((n1-1)*v1+(n2-1)*v2)/float(df)
- if not svar:
- svar = 1.0e-26
- t = (x1-x2)/math.sqrt(svar*(1.0/n1 + 1.0/n2))
- prob = betai(0.5*df,0.5,df/(df+t*t))
-
- if printit <> 0:
- statname = 'Independent samples T-test.'
- outputpairedstats(printit,writemode,
- name1,n1,x1,v1,min(a),max(a),
- name2,n2,x2,v2,min(b),max(b),
- statname,t,prob)
- return t,prob
-
-
-def lttest_rel (a,b,printit=0,name1='Sample1',name2='Sample2',writemode='a'):
- """
-Calculates the t-obtained T-test on TWO RELATED samples of scores,
-a and b. From Numerical Recipies, p.483. If printit=1, results are
-printed to the screen. If printit='filename', the results are output to
-'filename' using the given writemode (default=append). Returns t-value,
-and prob.
-
-Usage: lttest_rel(a,b,printit=0,name1='Sample1',name2='Sample2',writemode='a')
-Returns: t-value, two-tailed prob
-"""
- if len(a)<>len(b):
- raise ValueError, 'Unequal length lists in ttest_rel.'
- x1 = mean(a)
- x2 = mean(b)
- v1 = var(a)
- v2 = var(b)
- n = len(a)
- cov = 0
- for i in range(len(a)):
- cov = cov + (a[i]-x1) * (b[i]-x2)
- df = n-1
- cov = cov / float(df)
- sd = math.sqrt((v1+v2 - 2.0*cov)/float(n))
- t = (x1-x2)/sd
- prob = betai(0.5*df,0.5,df/(df+t*t))
-
- if printit <> 0:
- statname = 'Related samples T-test.'
- outputpairedstats(printit,writemode,
- name1,n,x1,v1,min(a),max(a),
- name2,n,x2,v2,min(b),max(b),
- statname,t,prob)
- return t, prob
-
-
-def lchisquare(f_obs,f_exp=None):
- """
-Calculates a one-way chi square for list of observed frequencies and returns
-the result. If no expected frequencies are given, the total N is assumed to
-be equally distributed across all groups.
-
-Usage: lchisquare(f_obs, f_exp=None) f_obs = list of observed cell freq.
-Returns: chisquare-statistic, associated p-value
-"""
- k = len(f_obs) # number of groups
- if f_exp == None:
- f_exp = [sum(f_obs)/float(k)] * len(f_obs) # create k bins with = freq.
- chisq = 0
- for i in range(len(f_obs)):
- chisq = chisq + (f_obs[i]-f_exp[i])**2 / float(f_exp[i])
- return chisq, chisqprob(chisq, k-1)
-
-
-def lks_2samp (data1,data2):
- """
-Computes the Kolmogorov-Smirnof statistic on 2 samples. From
-Numerical Recipies in C, page 493.
-
-Usage: lks_2samp(data1,data2) data1&2 are lists of values for 2 conditions
-Returns: KS D-value, associated p-value
-"""
- j1 = 0
- j2 = 0
- fn1 = 0.0
- fn2 = 0.0
- n1 = len(data1)
- n2 = len(data2)
- en1 = n1
- en2 = n2
- d = 0.0
- data1.sort()
- data2.sort()
- while j1 < n1 and j2 < n2:
- d1=data1[j1]
- d2=data2[j2]
- if d1 <= d2:
- fn1 = (j1)/float(en1)
- j1 = j1 + 1
- if d2 <= d1:
- fn2 = (j2)/float(en2)
- j2 = j2 + 1
- dt = (fn2-fn1)
- if math.fabs(dt) > math.fabs(d):
- d = dt
- try:
- en = math.sqrt(en1*en2/float(en1+en2))
- prob = ksprob((en+0.12+0.11/en)*abs(d))
- except:
- prob = 1.0
- return d, prob
-
-
-def lmannwhitneyu(x,y):
- """
-Calculates a Mann-Whitney U statistic on the provided scores and
-returns the result. Use only when the n in each condition is < 20 and
-you have 2 independent samples of ranks. NOTE: Mann-Whitney U is
-significant if the u-obtained is LESS THAN or equal to the critical
-value of U found in the tables. Equivalent to Kruskal-Wallis H with
-just 2 groups.
-
-Usage: lmannwhitneyu(data)
-Returns: u-statistic, one-tailed p-value (i.e., p(z(U)))
-"""
- n1 = len(x)
- n2 = len(y)
- ranked = rankdata(x+y)
- rankx = ranked[0:n1] # get the x-ranks
- ranky = ranked[n1:] # the rest are y-ranks
- u1 = n1*n2 + (n1*(n1+1))/2.0 - sum(rankx) # calc U for x
- u2 = n1*n2 - u1 # remainder is U for y
- bigu = max(u1,u2)
- smallu = min(u1,u2)
- proportion = bigu/float(n1*n2)
- T = math.sqrt(tiecorrect(ranked)) # correction factor for tied scores
- if T == 0:
- raise ValueError, 'All numbers are identical in lmannwhitneyu'
- sd = math.sqrt(T*n1*n2*(n1+n2+1)/12.0)
- z = abs((bigu-n1*n2/2.0) / sd) # normal approximation for prob calc
- return smallu, 1.0 - zprob(z) #, proportion
-
-
-def ltiecorrect(rankvals):
- """
-Corrects for ties in Mann Whitney U and Kruskal Wallis H tests. See
-Siegel, S. (1956) Nonparametric Statistics for the Behavioral Sciences.
-New York: McGraw-Hill. Code adapted from |Stat rankind.c code.
-
-Usage: ltiecorrect(rankvals)
-Returns: T correction factor for U or H
-"""
- sorted,posn = shellsort(rankvals)
- n = len(sorted)
- T = 0.0
- i = 0
- while (i<n-1):
- if sorted[i] == sorted[i+1]:
- nties = 1
- while (i<n-1) and (sorted[i] == sorted[i+1]):
- nties = nties +1
- i = i +1
- T = T + nties**3 - nties
- i = i+1
- T = T / float(n**3-n)
- return 1.0 - T
-
-
-def lranksums(x,y):
- """
-Calculates the rank sums statistic on the provided scores and
-returns the result. Use only when the n in each condition is > 20 and you
-have 2 independent samples of ranks.
-
-Usage: lranksums(x,y)
-Returns: a z-statistic, two-tailed p-value
-"""
- n1 = len(x)
- n2 = len(y)
- alldata = x+y
- ranked = rankdata(alldata)
- x = ranked[:n1]
- y = ranked[n1:]
- s = sum(x)
- expected = n1*(n1+n2+1) / 2.0
- z = (s - expected) / math.sqrt(n1*n2*(n1+n2+1)/12.0)
- prob = 2*(1.0 -zprob(abs(z)))
- return z, prob
-
-
-def lwilcoxont(x,y):
- """
-Calculates the Wilcoxon T-test for related samples and returns the
-result. A non-parametric T-test.
-
-Usage: lwilcoxont(x,y)
-Returns: a t-statistic, two-tail probability estimate
-"""
- if len(x) <> len(y):
- raise ValueError, 'Unequal N in wilcoxont. Aborting.'
- d=[]
- for i in range(len(x)):
- diff = x[i] - y[i]
- if diff <> 0:
- d.append(diff)
- count = len(d)
- absd = map(abs,d)
- absranked = rankdata(absd)
- r_plus = 0.0
- r_minus = 0.0
- for i in range(len(absd)):
- if d[i] < 0:
- r_minus = r_minus + absranked[i]
- else:
- r_plus = r_plus + absranked[i]
- wt = min(r_plus, r_minus)
- mn = count * (count+1) * 0.25
- se = math.sqrt(count*(count+1)*(2.0*count+1.0)/24.0)
- z = math.fabs(wt-mn) / se
- prob = 2*(1.0 -zprob(abs(z)))
- return wt, prob
-
-
-def lkruskalwallish(*args):
- """
-The Kruskal-Wallis H-test is a non-parametric ANOVA for 3 or more
-groups, requiring at least 5 subjects in each group. This function
-calculates the Kruskal-Wallis H-test for 3 or more independent samples
-and returns the result.
-
-Usage: lkruskalwallish(*args)
-Returns: H-statistic (corrected for ties), associated p-value
-"""
- args = list(args)
- n = [0]*len(args)
- all = []
- n = map(len,args)
- for i in range(len(args)):
- all = all + args[i]
- ranked = rankdata(all)
- T = tiecorrect(ranked)
- for i in range(len(args)):
- args[i] = ranked[0:n[i]]
- del ranked[0:n[i]]
- rsums = []
- for i in range(len(args)):
- rsums.append(sum(args[i])**2)
- rsums[i] = rsums[i] / float(n[i])
- ssbn = sum(rsums)
- totaln = sum(n)
- h = 12.0 / (totaln*(totaln+1)) * ssbn - 3*(totaln+1)
- df = len(args) - 1
- if T == 0:
- raise ValueError, 'All numbers are identical in lkruskalwallish'
- h = h / float(T)
- return h, chisqprob(h,df)
-
-
-def lfriedmanchisquare(*args):
- """
-Friedman Chi-Square is a non-parametric, one-way within-subjects
-ANOVA. This function calculates the Friedman Chi-square test for repeated
-measures and returns the result, along with the associated probability
-value. It assumes 3 or more repeated measures. Only 3 levels requires a
-minimum of 10 subjects in the study. Four levels requires 5 subjects per
-level(??).
-
-Usage: lfriedmanchisquare(*args)
-Returns: chi-square statistic, associated p-value
-"""
- k = len(args)
- if k < 3:
- raise ValueError, 'Less than 3 levels. Friedman test not appropriate.'
- n = len(args[0])
- data = apply(pstat.abut,tuple(args))
- for i in range(len(data)):
- data[i] = rankdata(data[i])
- ssbn = 0
- for i in range(k):
- ssbn = ssbn + sum(args[i])**2
- chisq = 12.0 / (k*n*(k+1)) * ssbn - 3*n*(k+1)
- return chisq, chisqprob(chisq,k-1)
-
-
-####################################
-#### PROBABILITY CALCULATIONS ####
-####################################
-
-def lchisqprob(chisq,df):
- """
-Returns the (1-tailed) probability value associated with the provided
-chi-square value and df. Adapted from chisq.c in Gary Perlman's |Stat.
-
-Usage: lchisqprob(chisq,df)
-"""
- BIG = 20.0
- def ex(x):
- BIG = 20.0
- if x < -BIG:
- return 0.0
- else:
- return math.exp(x)
-
- if chisq <=0 or df < 1:
- return 1.0
- a = 0.5 * chisq
- if df%2 == 0:
- even = 1
- else:
- even = 0
- if df > 1:
- y = ex(-a)
- if even:
- s = y
- else:
- s = 2.0 * zprob(-math.sqrt(chisq))
- if (df > 2):
- chisq = 0.5 * (df - 1.0)
- if even:
- z = 1.0
- else:
- z = 0.5
- if a > BIG:
- if even:
- e = 0.0
- else:
- e = math.log(math.sqrt(math.pi))
- c = math.log(a)
- while (z <= chisq):
- e = math.log(z) + e
- s = s + ex(c*z-a-e)
- z = z + 1.0
- return s
- else:
- if even:
- e = 1.0
- else:
- e = 1.0 / math.sqrt(math.pi) / math.sqrt(a)
- c = 0.0
- while (z <= chisq):
- e = e * (a/float(z))
- c = c + e
- z = z + 1.0
- return (c*y+s)
- else:
- return s
-
-
-def lerfcc(x):
- """
-Returns the complementary error function erfc(x) with fractional
-error everywhere less than 1.2e-7. Adapted from Numerical Recipies.
-
-Usage: lerfcc(x)
-"""
- z = abs(x)
- t = 1.0 / (1.0+0.5*z)
- ans = t * math.exp(-z*z-1.26551223 + t*(1.00002368+t*(0.37409196+t*(0.09678418+t*(-0.18628806+t*(0.27886807+t*(-1.13520398+t*(1.48851587+t*(-0.82215223+t*0.17087277)))))))))
- if x >= 0:
- return ans
- else:
- return 2.0 - ans
-
-
-def lzprob(z):
- """
-Returns the area under the normal curve 'to the left of' the given z value.
-Thus,
- for z<0, zprob(z) = 1-tail probability
- for z>0, 1.0-zprob(z) = 1-tail probability
- for any z, 2.0*(1.0-zprob(abs(z))) = 2-tail probability
-Adapted from z.c in Gary Perlman's |Stat.
-
-Usage: lzprob(z)
-"""
- Z_MAX = 6.0 # maximum meaningful z-value
- if z == 0.0:
- x = 0.0
- else:
- y = 0.5 * math.fabs(z)
- if y >= (Z_MAX*0.5):
- x = 1.0
- elif (y < 1.0):
- w = y*y
- x = ((((((((0.000124818987 * w
- -0.001075204047) * w +0.005198775019) * w
- -0.019198292004) * w +0.059054035642) * w
- -0.151968751364) * w +0.319152932694) * w
- -0.531923007300) * w +0.797884560593) * y * 2.0
- else:
- y = y - 2.0
- x = (((((((((((((-0.000045255659 * y
- +0.000152529290) * y -0.000019538132) * y
- -0.000676904986) * y +0.001390604284) * y
- -0.000794620820) * y -0.002034254874) * y
- +0.006549791214) * y -0.010557625006) * y
- +0.011630447319) * y -0.009279453341) * y
- +0.005353579108) * y -0.002141268741) * y
- +0.000535310849) * y +0.999936657524
- if z > 0.0:
- prob = ((x+1.0)*0.5)
- else:
- prob = ((1.0-x)*0.5)
- return prob
-
-
-def lksprob(alam):
- """
-Computes a Kolmolgorov-Smirnov t-test significance level. Adapted from
-Numerical Recipies.
-
-Usage: lksprob(alam)
-"""
- fac = 2.0
- sum = 0.0
- termbf = 0.0
- a2 = -2.0*alam*alam
- for j in range(1,201):
- term = fac*math.exp(a2*j*j)
- sum = sum + term
- if math.fabs(term) <= (0.001*termbf) or math.fabs(term) < (1.0e-8*sum):
- return sum
- fac = -fac
- termbf = math.fabs(term)
- return 1.0 # Get here only if fails to converge; was 0.0!!
-
-
-def lfprob (dfnum, dfden, F):
- """
-Returns the (1-tailed) significance level (p-value) of an F
-statistic given the degrees of freedom for the numerator (dfR-dfF) and
-the degrees of freedom for the denominator (dfF).
-
-Usage: lfprob(dfnum, dfden, F) where usually dfnum=dfbn, dfden=dfwn
-"""
- p = betai(0.5*dfden, 0.5*dfnum, dfden/float(dfden+dfnum*F))
- return p
-
-
-def lbetacf(a,b,x):
- """
-This function evaluates the continued fraction form of the incomplete
-Beta function, betai. (Adapted from: Numerical Recipies in C.)
-
-Usage: lbetacf(a,b,x)
-"""
- ITMAX = 200
- EPS = 3.0e-7
-
- bm = az = am = 1.0
- qab = a+b
- qap = a+1.0
- qam = a-1.0
- bz = 1.0-qab*x/qap
- for i in range(ITMAX+1):
- em = float(i+1)
- tem = em + em
- d = em*(b-em)*x/((qam+tem)*(a+tem))
- ap = az + d*am
- bp = bz+d*bm
- d = -(a+em)*(qab+em)*x/((qap+tem)*(a+tem))
- app = ap+d*az
- bpp = bp+d*bz
- aold = az
- am = ap/bpp
- bm = bp/bpp
- az = app/bpp
- bz = 1.0
- if (abs(az-aold)<(EPS*abs(az))):
- return az
- print 'a or b too big, or ITMAX too small in Betacf.'
-
-
-def lgammln(xx):
- """
-Returns the gamma function of xx.
- Gamma(z) = Integral(0,infinity) of t^(z-1)exp(-t) dt.
-(Adapted from: Numerical Recipies in C.)
-
-Usage: lgammln(xx)
-"""
-
- coeff = [76.18009173, -86.50532033, 24.01409822, -1.231739516,
- 0.120858003e-2, -0.536382e-5]
- x = xx - 1.0
- tmp = x + 5.5
- tmp = tmp - (x+0.5)*math.log(tmp)
- ser = 1.0
- for j in range(len(coeff)):
- x = x + 1
- ser = ser + coeff[j]/x
- return -tmp + math.log(2.50662827465*ser)
-
-
-def lbetai(a,b,x):
- """
-Returns the incomplete beta function:
-
- I-sub-x(a,b) = 1/B(a,b)*(Integral(0,x) of t^(a-1)(1-t)^(b-1) dt)
-
-where a,b>0 and B(a,b) = G(a)*G(b)/(G(a+b)) where G(a) is the gamma
-function of a. The continued fraction formulation is implemented here,
-using the betacf function. (Adapted from: Numerical Recipies in C.)
-
-Usage: lbetai(a,b,x)
-"""
- if (x<0.0 or x>1.0):
- raise ValueError, 'Bad x in lbetai'
- if (x==0.0 or x==1.0):
- bt = 0.0
- else:
- bt = math.exp(gammln(a+b)-gammln(a)-gammln(b)+a*math.log(x)+b*
- math.log(1.0-x))
- if (x<(a+1.0)/(a+b+2.0)):
- return bt*betacf(a,b,x)/float(a)
- else:
- return 1.0-bt*betacf(b,a,1.0-x)/float(b)
-
-
-####################################
-####### ANOVA CALCULATIONS #######
-####################################
-
-def lF_oneway(*lists):
- """
-Performs a 1-way ANOVA, returning an F-value and probability given
-any number of groups. From Heiman, pp.394-7.
-
-Usage: F_oneway(*lists) where *lists is any number of lists, one per
- treatment group
-Returns: F value, one-tailed p-value
-"""
- a = len(lists) # ANOVA on 'a' groups, each in it's own list
- means = [0]*a
- vars = [0]*a
- ns = [0]*a
- alldata = []
- tmp = map(N.array,lists)
- means = map(amean,tmp)
- vars = map(avar,tmp)
- ns = map(len,lists)
- for i in range(len(lists)):
- alldata = alldata + lists[i]
- alldata = N.array(alldata)
- bign = len(alldata)
- sstot = ass(alldata)-(asquare_of_sums(alldata)/float(bign))
- ssbn = 0
- for list in lists:
- ssbn = ssbn + asquare_of_sums(N.array(list))/float(len(list))
- ssbn = ssbn - (asquare_of_sums(alldata)/float(bign))
- sswn = sstot-ssbn
- dfbn = a-1
- dfwn = bign - a
- msb = ssbn/float(dfbn)
- msw = sswn/float(dfwn)
- f = msb/msw
- prob = fprob(dfbn,dfwn,f)
- return f, prob
-
-
-def lF_value (ER,EF,dfnum,dfden):
- """
-Returns an F-statistic given the following:
- ER = error associated with the null hypothesis (the Restricted model)
- EF = error associated with the alternate hypothesis (the Full model)
- dfR-dfF = degrees of freedom of the numerator
- dfF = degrees of freedom associated with the denominator/Full model
-
-Usage: lF_value(ER,EF,dfnum,dfden)
-"""
- return ((ER-EF)/float(dfnum) / (EF/float(dfden)))
-
-
-####################################
-######## SUPPORT FUNCTIONS #######
-####################################
-
-def writecc (listoflists,file,writetype='w',extra=2):
- """
-Writes a list of lists to a file in columns, customized by the max
-size of items within the columns (max size of items in col, +2 characters)
-to specified file. File-overwrite is the default.
-
-Usage: writecc (listoflists,file,writetype='w',extra=2)
-Returns: None
-"""
- if type(listoflists[0]) not in [ListType,TupleType]:
- listoflists = [listoflists]
- outfile = open(file,writetype)
- rowstokill = []
- list2print = copy.deepcopy(listoflists)
- for i in range(len(listoflists)):
- if listoflists[i] == ['\n'] or listoflists[i]=='\n' or listoflists[i]=='dashes':
- rowstokill = rowstokill + [i]
- rowstokill.reverse()
- for row in rowstokill:
- del list2print[row]
- maxsize = [0]*len(list2print[0])
- for col in range(len(list2print[0])):
- items = pstat.colex(list2print,col)
- items = map(pstat.makestr,items)
- maxsize[col] = max(map(len,items)) + extra
- for row in listoflists:
- if row == ['\n'] or row == '\n':
- outfile.write('\n')
- elif row == ['dashes'] or row == 'dashes':
- dashes = [0]*len(maxsize)
- for j in range(len(maxsize)):
- dashes[j] = '-'*(maxsize[j]-2)
- outfile.write(pstat.lineincustcols(dashes,maxsize))
- else:
- outfile.write(pstat.lineincustcols(row,maxsize))
- outfile.write('\n')
- outfile.close()
- return None
-
-
-def lincr(l,cap): # to increment a list up to a max-list of 'cap'
- """
-Simulate a counting system from an n-dimensional list.
-
-Usage: lincr(l,cap) l=list to increment, cap=max values for each list pos'n
-Returns: next set of values for list l, OR -1 (if overflow)
-"""
- l[0] = l[0] + 1 # e.g., [0,0,0] --> [2,4,3] (=cap)
- for i in range(len(l)):
- if l[i] > cap[i] and i < len(l)-1: # if carryover AND not done
- l[i] = 0
- l[i+1] = l[i+1] + 1
- elif l[i] > cap[i] and i == len(l)-1: # overflow past last column, must be finished
- l = -1
- return l
-
-
-def lsum (inlist):
- """
-Returns the sum of the items in the passed list.
-
-Usage: lsum(inlist)
-"""
- s = 0
- for item in inlist:
- s = s + item
- return s
-
-
-def lcumsum (inlist):
- """
-Returns a list consisting of the cumulative sum of the items in the
-passed list.
-
-Usage: lcumsum(inlist)
-"""
- newlist = copy.deepcopy(inlist)
- for i in range(1,len(newlist)):
- newlist[i] = newlist[i] + newlist[i-1]
- return newlist
-
-
-def lss(inlist):
- """
-Squares each value in the passed list, adds up these squares and
-returns the result.
-
-Usage: lss(inlist)
-"""
- ss = 0
- for item in inlist:
- ss = ss + item*item
- return ss
-
-
-def lsummult (list1,list2):
- """
-Multiplies elements in list1 and list2, element by element, and
-returns the sum of all resulting multiplications. Must provide equal
-length lists.
-
-Usage: lsummult(list1,list2)
-"""
- if len(list1) <> len(list2):
- raise ValueError, "Lists not equal length in summult."
- s = 0
- for item1,item2 in pstat.abut(list1,list2):
- s = s + item1*item2
- return s
-
-
-def lsumdiffsquared(x,y):
- """
-Takes pairwise differences of the values in lists x and y, squares
-these differences, and returns the sum of these squares.
-
-Usage: lsumdiffsquared(x,y)
-Returns: sum[(x[i]-y[i])**2]
-"""
- sds = 0
- for i in range(len(x)):
- sds = sds + (x[i]-y[i])**2
- return sds
-
-
-def lsquare_of_sums(inlist):
- """
-Adds the values in the passed list, squares the sum, and returns
-the result.
-
-Usage: lsquare_of_sums(inlist)
-Returns: sum(inlist[i])**2
-"""
- s = sum(inlist)
- return float(s)*s
-
-
-def lshellsort(inlist):
- """
-Shellsort algorithm. Sorts a 1D-list.
-
-Usage: lshellsort(inlist)
-Returns: sorted-inlist, sorting-index-vector (for original list)
-"""
- n = len(inlist)
- svec = copy.deepcopy(inlist)
- ivec = range(n)
- gap = n/2 # integer division needed
- while gap >0:
- for i in range(gap,n):
- for j in range(i-gap,-1,-gap):
- while j>=0 and svec[j]>svec[j+gap]:
- temp = svec[j]
- svec[j] = svec[j+gap]
- svec[j+gap] = temp
- itemp = ivec[j]
- ivec[j] = ivec[j+gap]
- ivec[j+gap] = itemp
- gap = gap / 2 # integer division needed
-# svec is now sorted inlist, and ivec has the order svec[i] = vec[ivec[i]]
- return svec, ivec
-
-
-def lrankdata(inlist):
- """
-Ranks the data in inlist, dealing with ties appropritely. Assumes
-a 1D inlist. Adapted from Gary Perlman's |Stat ranksort.
-
-Usage: lrankdata(inlist)
-Returns: a list of length equal to inlist, containing rank scores
-"""
- n = len(inlist)
- svec, ivec = shellsort(inlist)
- sumranks = 0
- dupcount = 0
- newlist = [0]*n
- for i in range(n):
- sumranks = sumranks + i
- dupcount = dupcount + 1
- if i==n-1 or svec[i] <> svec[i+1]:
- averank = sumranks / float(dupcount) + 1
- for j in range(i-dupcount+1,i+1):
- newlist[ivec[j]] = averank
- sumranks = 0
- dupcount = 0
- return newlist
-
-
-def outputpairedstats(fname,writemode,name1,n1,m1,se1,min1,max1,name2,n2,m2,se2,min2,max2,statname,stat,prob):
- """
-Prints or write to a file stats for two groups, using the name, n,
-mean, sterr, min and max for each group, as well as the statistic name,
-its value, and the associated p-value.
-
-Usage: outputpairedstats(fname,writemode,
- name1,n1,mean1,stderr1,min1,max1,
- name2,n2,mean2,stderr2,min2,max2,
- statname,stat,prob)
-Returns: None
-"""
- suffix = '' # for *s after the p-value
- try:
- x = prob.shape
- prob = prob[0]
- except:
- pass
- if prob < 0.001: suffix = ' ***'
- elif prob < 0.01: suffix = ' **'
- elif prob < 0.05: suffix = ' *'
- title = [['Name','N','Mean','SD','Min','Max']]
- lofl = title+[[name1,n1,round(m1,3),round(math.sqrt(se1),3),min1,max1],
- [name2,n2,round(m2,3),round(math.sqrt(se2),3),min2,max2]]
- if type(fname)<>StringType or len(fname)==0:
- print
- print statname
- print
- pstat.printcc(lofl)
- print
- try:
- if stat.shape == ():
- stat = stat[0]
- if prob.shape == ():
- prob = prob[0]
- except:
- pass
- print 'Test statistic = ',round(stat,3),' p = ',round(prob,3),suffix
- print
- else:
- file = open(fname,writemode)
- file.write('\n'+statname+'\n\n')
- file.close()
- writecc(lofl,fname,'a')
- file = open(fname,'a')
- try:
- if stat.shape == ():
- stat = stat[0]
- if prob.shape == ():
- prob = prob[0]
- except:
- pass
- file.write(pstat.list2string(['\nTest statistic = ',round(stat,4),' p = ',round(prob,4),suffix,'\n\n']))
- file.close()
- return None
-
-
-def lfindwithin (data):
- """
-Returns an integer representing a binary vector, where 1=within-
-subject factor, 0=between. Input equals the entire data 2D list (i.e.,
-column 0=random factor, column -1=measured values (those two are skipped).
-Note: input data is in |Stat format ... a list of lists ("2D list") with
-one row per measured value, first column=subject identifier, last column=
-score, one in-between column per factor (these columns contain level
-designations on each factor). See also stats.anova.__doc__.
-
-Usage: lfindwithin(data) data in |Stat format
-"""
-
- numfact = len(data[0])-1
- withinvec = 0
- for col in range(1,numfact):
- examplelevel = pstat.unique(pstat.colex(data,col))[0]
- rows = pstat.linexand(data,col,examplelevel) # get 1 level of this factor
- factsubjs = pstat.unique(pstat.colex(rows,0))
- allsubjs = pstat.unique(pstat.colex(data,0))
- if len(factsubjs) == len(allsubjs): # fewer Ss than scores on this factor?
- withinvec = withinvec + (1 << col)
- return withinvec
-
-
-#########################################################
-#########################################################
-####### DISPATCH LISTS AND TUPLES TO ABOVE FCNS #########
-#########################################################
-#########################################################
-
-## CENTRAL TENDENCY:
-geometricmean = Dispatch ( (lgeometricmean, (ListType, TupleType)), )
-harmonicmean = Dispatch ( (lharmonicmean, (ListType, TupleType)), )
-mean = Dispatch ( (lmean, (ListType, TupleType)), )
-median = Dispatch ( (lmedian, (ListType, TupleType)), )
-medianscore = Dispatch ( (lmedianscore, (ListType, TupleType)), )
-mode = Dispatch ( (lmode, (ListType, TupleType)), )
-
-## MOMENTS:
-moment = Dispatch ( (lmoment, (ListType, TupleType)), )
-variation = Dispatch ( (lvariation, (ListType, TupleType)), )
-skew = Dispatch ( (lskew, (ListType, TupleType)), )
-kurtosis = Dispatch ( (lkurtosis, (ListType, TupleType)), )
-describe = Dispatch ( (ldescribe, (ListType, TupleType)), )
-
-## FREQUENCY STATISTICS:
-itemfreq = Dispatch ( (litemfreq, (ListType, TupleType)), )
-scoreatpercentile = Dispatch ( (lscoreatpercentile, (ListType, TupleType)), )
-percentileofscore = Dispatch ( (lpercentileofscore, (ListType, TupleType)), )
-histogram = Dispatch ( (lhistogram, (ListType, TupleType)), )
-cumfreq = Dispatch ( (lcumfreq, (ListType, TupleType)), )
-relfreq = Dispatch ( (lrelfreq, (ListType, TupleType)), )
-
-## VARIABILITY:
-obrientransform = Dispatch ( (lobrientransform, (ListType, TupleType)), )
-samplevar = Dispatch ( (lsamplevar, (ListType, TupleType)), )
-samplestdev = Dispatch ( (lsamplestdev, (ListType, TupleType)), )
-var = Dispatch ( (lvar, (ListType, TupleType)), )
-stdev = Dispatch ( (lstdev, (ListType, TupleType)), )
-sterr = Dispatch ( (lsterr, (ListType, TupleType)), )
-sem = Dispatch ( (lsem, (ListType, TupleType)), )
-z = Dispatch ( (lz, (ListType, TupleType)), )
-zs = Dispatch ( (lzs, (ListType, TupleType)), )
-
-## TRIMMING FCNS:
-trimboth = Dispatch ( (ltrimboth, (ListType, TupleType)), )
-trim1 = Dispatch ( (ltrim1, (ListType, TupleType)), )
-
-## CORRELATION FCNS:
-paired = Dispatch ( (lpaired, (ListType, TupleType)), )
-pearsonr = Dispatch ( (lpearsonr, (ListType, TupleType)), )
-spearmanr = Dispatch ( (lspearmanr, (ListType, TupleType)), )
-pointbiserialr = Dispatch ( (lpointbiserialr, (ListType, TupleType)), )
-kendalltau = Dispatch ( (lkendalltau, (ListType, TupleType)), )
-linregress = Dispatch ( (llinregress, (ListType, TupleType)), )
-
-## INFERENTIAL STATS:
-ttest_1samp = Dispatch ( (lttest_1samp, (ListType, TupleType)), )
-ttest_ind = Dispatch ( (lttest_ind, (ListType, TupleType)), )
-ttest_rel = Dispatch ( (lttest_rel, (ListType, TupleType)), )
-chisquare = Dispatch ( (lchisquare, (ListType, TupleType)), )
-ks_2samp = Dispatch ( (lks_2samp, (ListType, TupleType)), )
-mannwhitneyu = Dispatch ( (lmannwhitneyu, (ListType, TupleType)), )
-ranksums = Dispatch ( (lranksums, (ListType, TupleType)), )
-tiecorrect = Dispatch ( (ltiecorrect, (ListType, TupleType)), )
-wilcoxont = Dispatch ( (lwilcoxont, (ListType, TupleType)), )
-kruskalwallish = Dispatch ( (lkruskalwallish, (ListType, TupleType)), )
-friedmanchisquare = Dispatch ( (lfriedmanchisquare, (ListType, TupleType)), )
-
-## PROBABILITY CALCS:
-chisqprob = Dispatch ( (lchisqprob, (IntType, FloatType)), )
-zprob = Dispatch ( (lzprob, (IntType, FloatType)), )
-ksprob = Dispatch ( (lksprob, (IntType, FloatType)), )
-fprob = Dispatch ( (lfprob, (IntType, FloatType)), )
-betacf = Dispatch ( (lbetacf, (IntType, FloatType)), )
-betai = Dispatch ( (lbetai, (IntType, FloatType)), )
-erfcc = Dispatch ( (lerfcc, (IntType, FloatType)), )
-gammln = Dispatch ( (lgammln, (IntType, FloatType)), )
-
-## ANOVA FUNCTIONS:
-F_oneway = Dispatch ( (lF_oneway, (ListType, TupleType)), )
-F_value = Dispatch ( (lF_value, (ListType, TupleType)), )
-
-## SUPPORT FUNCTIONS:
-incr = Dispatch ( (lincr, (ListType, TupleType)), )
-sum = Dispatch ( (lsum, (ListType, TupleType)), )
-cumsum = Dispatch ( (lcumsum, (ListType, TupleType)), )
-ss = Dispatch ( (lss, (ListType, TupleType)), )
-summult = Dispatch ( (lsummult, (ListType, TupleType)), )
-square_of_sums = Dispatch ( (lsquare_of_sums, (ListType, TupleType)), )
-sumdiffsquared = Dispatch ( (lsumdiffsquared, (ListType, TupleType)), )
-shellsort = Dispatch ( (lshellsort, (ListType, TupleType)), )
-rankdata = Dispatch ( (lrankdata, (ListType, TupleType)), )
-findwithin = Dispatch ( (lfindwithin, (ListType, TupleType)), )
-
-
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-#============= THE ARRAY-VERSION OF THE STATS FUNCTIONS ===============
-
-try: # DEFINE THESE *ONLY* IF NUMERIC IS AVAILABLE
- import numpy as N
- import numpy.linalg as LA
-
-
-#####################################
-######## ACENTRAL TENDENCY ########
-#####################################
-
- def ageometricmean (inarray,dimension=None,keepdims=0):
- """
-Calculates the geometric mean of the values in the passed array.
-That is: n-th root of (x1 * x2 * ... * xn). Defaults to ALL values in
-the passed array. Use dimension=None to flatten array first. REMEMBER: if
-dimension=0, it collapses over dimension 0 ('rows' in a 2D array) only, and
-if dimension is a sequence, it collapses over all specified dimensions. If
-keepdims is set to 1, the resulting array will have as many dimensions as
-inarray, with only 1 'level' per dim that was collapsed over.
-
-Usage: ageometricmean(inarray,dimension=None,keepdims=0)
-Returns: geometric mean computed over dim(s) listed in dimension
-"""
- inarray = N.array(inarray,N.float_)
- if dimension == None:
- inarray = N.ravel(inarray)
- size = len(inarray)
- mult = N.power(inarray,1.0/size)
- mult = N.multiply.reduce(mult)
- elif type(dimension) in [IntType,FloatType]:
- size = inarray.shape[dimension]
- mult = N.power(inarray,1.0/size)
- mult = N.multiply.reduce(mult,dimension)
- if keepdims == 1:
- shp = list(inarray.shape)
- shp[dimension] = 1
- sum = N.reshape(sum,shp)
- else: # must be a SEQUENCE of dims to average over
- dims = list(dimension)
- dims.sort()
- dims.reverse()
- size = N.array(N.multiply.reduce(N.take(inarray.shape,dims)),N.float_)
- mult = N.power(inarray,1.0/size)
- for dim in dims:
- mult = N.multiply.reduce(mult,dim)
- if keepdims == 1:
- shp = list(inarray.shape)
- for dim in dims:
- shp[dim] = 1
- mult = N.reshape(mult,shp)
- return mult
-
-
- def aharmonicmean (inarray,dimension=None,keepdims=0):
- """
-Calculates the harmonic mean of the values in the passed array.
-That is: n / (1/x1 + 1/x2 + ... + 1/xn). Defaults to ALL values in
-the passed array. Use dimension=None to flatten array first. REMEMBER: if
-dimension=0, it collapses over dimension 0 ('rows' in a 2D array) only, and
-if dimension is a sequence, it collapses over all specified dimensions. If
-keepdims is set to 1, the resulting array will have as many dimensions as
-inarray, with only 1 'level' per dim that was collapsed over.
-
-Usage: aharmonicmean(inarray,dimension=None,keepdims=0)
-Returns: harmonic mean computed over dim(s) in dimension
-"""
- inarray = inarray.astype(N.float_)
- if dimension == None:
- inarray = N.ravel(inarray)
- size = len(inarray)
- s = N.add.reduce(1.0 / inarray)
- elif type(dimension) in [IntType,FloatType]:
- size = float(inarray.shape[dimension])
- s = N.add.reduce(1.0/inarray, dimension)
- if keepdims == 1:
- shp = list(inarray.shape)
- shp[dimension] = 1
- s = N.reshape(s,shp)
- else: # must be a SEQUENCE of dims to average over
- dims = list(dimension)
- dims.sort()
- nondims = []
- for i in range(len(inarray.shape)):
- if i not in dims:
- nondims.append(i)
- tinarray = N.transpose(inarray,nondims+dims) # put keep-dims first
- idx = [0] *len(nondims)
- if idx == []:
- size = len(N.ravel(inarray))
- s = asum(1.0 / inarray)
- if keepdims == 1:
- s = N.reshape([s],N.ones(len(inarray.shape)))
- else:
- idx[0] = -1
- loopcap = N.array(tinarray.shape[0:len(nondims)]) -1
- s = N.zeros(loopcap+1,N.float_)
- while incr(idx,loopcap) <> -1:
- s[idx] = asum(1.0/tinarray[idx])
- size = N.multiply.reduce(N.take(inarray.shape,dims))
- if keepdims == 1:
- shp = list(inarray.shape)
- for dim in dims:
- shp[dim] = 1
- s = N.reshape(s,shp)
- return size / s
-
-
- def amean (inarray,dimension=None,keepdims=0):
- """
-Calculates the arithmatic mean of the values in the passed array.
-That is: 1/n * (x1 + x2 + ... + xn). Defaults to ALL values in the
-passed array. Use dimension=None to flatten array first. REMEMBER: if
-dimension=0, it collapses over dimension 0 ('rows' in a 2D array) only, and
-if dimension is a sequence, it collapses over all specified dimensions. If
-keepdims is set to 1, the resulting array will have as many dimensions as
-inarray, with only 1 'level' per dim that was collapsed over.
-
-Usage: amean(inarray,dimension=None,keepdims=0)
-Returns: arithematic mean calculated over dim(s) in dimension
-"""
- if inarray.dtype in [N.int_, N.short,N.ubyte]:
- inarray = inarray.astype(N.float_)
- if dimension == None:
- inarray = N.ravel(inarray)
- sum = N.add.reduce(inarray)
- denom = float(len(inarray))
- elif type(dimension) in [IntType,FloatType]:
- sum = asum(inarray,dimension)
- denom = float(inarray.shape[dimension])
- if keepdims == 1:
- shp = list(inarray.shape)
- shp[dimension] = 1
- sum = N.reshape(sum,shp)
- else: # must be a TUPLE of dims to average over
- dims = list(dimension)
- dims.sort()
- dims.reverse()
- sum = inarray *1.0
- for dim in dims:
- sum = N.add.reduce(sum,dim)
- denom = N.array(N.multiply.reduce(N.take(inarray.shape,dims)),N.float_)
- if keepdims == 1:
- shp = list(inarray.shape)
- for dim in dims:
- shp[dim] = 1
- sum = N.reshape(sum,shp)
- return sum/denom
-
-
- def amedian (inarray,numbins=1000):
- """
-Calculates the COMPUTED median value of an array of numbers, given the
-number of bins to use for the histogram (more bins approaches finding the
-precise median value of the array; default number of bins = 1000). From
-G.W. Heiman's Basic Stats, or CRC Probability & Statistics.
-NOTE: THIS ROUTINE ALWAYS uses the entire passed array (flattens it first).
-
-Usage: amedian(inarray,numbins=1000)
-Returns: median calculated over ALL values in inarray
-"""
- inarray = N.ravel(inarray)
- (hist, smallest, binsize, extras) = ahistogram(inarray,numbins,[min(inarray),max(inarray)])
- cumhist = N.cumsum(hist) # make cumulative histogram
- otherbins = N.greater_equal(cumhist,len(inarray)/2.0)
- otherbins = list(otherbins) # list of 0/1s, 1s start at median bin
- cfbin = otherbins.index(1) # get 1st(!) index holding 50%ile score
- LRL = smallest + binsize*cfbin # get lower read limit of that bin
- cfbelow = N.add.reduce(hist[0:cfbin]) # cum. freq. below bin
- freq = hist[cfbin] # frequency IN the 50%ile bin
- median = LRL + ((len(inarray)/2.0-cfbelow)/float(freq))*binsize # MEDIAN
- return median
-
-
- def amedianscore (inarray,dimension=None):
- """
-Returns the 'middle' score of the passed array. If there is an even
-number of scores, the mean of the 2 middle scores is returned. Can function
-with 1D arrays, or on the FIRST dimension of 2D arrays (i.e., dimension can
-be None, to pre-flatten the array, or else dimension must equal 0).
-
-Usage: amedianscore(inarray,dimension=None)
-Returns: 'middle' score of the array, or the mean of the 2 middle scores
-"""
- if dimension == None:
- inarray = N.ravel(inarray)
- dimension = 0
- inarray = N.sort(inarray,dimension)
- if inarray.shape[dimension] % 2 == 0: # if even number of elements
- indx = inarray.shape[dimension]/2 # integer division correct
- median = N.asarray(inarray[indx]+inarray[indx-1]) / 2.0
- else:
- indx = inarray.shape[dimension] / 2 # integer division correct
- median = N.take(inarray,[indx],dimension)
- if median.shape == (1,):
- median = median[0]
- return median
-
-
- def amode(a, dimension=None):
- """
-Returns an array of the modal (most common) score in the passed array.
-If there is more than one such score, ONLY THE FIRST is returned.
-The bin-count for the modal values is also returned. Operates on whole
-array (dimension=None), or on a given dimension.
-
-Usage: amode(a, dimension=None)
-Returns: array of bin-counts for mode(s), array of corresponding modal values
-"""
-
- if dimension == None:
- a = N.ravel(a)
- dimension = 0
- scores = pstat.aunique(N.ravel(a)) # get ALL unique values
- testshape = list(a.shape)
- testshape[dimension] = 1
- oldmostfreq = N.zeros(testshape)
- oldcounts = N.zeros(testshape)
- for score in scores:
- template = N.equal(a,score)
- counts = asum(template,dimension,1)
- mostfrequent = N.where(counts>oldcounts,score,oldmostfreq)
- oldcounts = N.where(counts>oldcounts,counts,oldcounts)
- oldmostfreq = mostfrequent
- return oldcounts, mostfrequent
-
-
- def atmean(a,limits=None,inclusive=(1,1)):
- """
-Returns the arithmetic mean of all values in an array, ignoring values
-strictly outside the sequence passed to 'limits'. Note: either limit
-in the sequence, or the value of limits itself, can be set to None. The
-inclusive list/tuple determines whether the lower and upper limiting bounds
-(respectively) are open/exclusive (0) or closed/inclusive (1).
-
-Usage: atmean(a,limits=None,inclusive=(1,1))
-"""
- if a.dtype in [N.int_, N.short,N.ubyte]:
- a = a.astype(N.float_)
- if limits == None:
- return mean(a)
- assert type(limits) in [ListType,TupleType,N.ndarray], "Wrong type for limits in atmean"
- if inclusive[0]: lowerfcn = N.greater_equal
- else: lowerfcn = N.greater
- if inclusive[1]: upperfcn = N.less_equal
- else: upperfcn = N.less
- if limits[0] > N.maximum.reduce(N.ravel(a)) or limits[1] < N.minimum.reduce(N.ravel(a)):
- raise ValueError, "No array values within given limits (atmean)."
- elif limits[0]==None and limits[1]<>None:
- mask = upperfcn(a,limits[1])
- elif limits[0]<>None and limits[1]==None:
- mask = lowerfcn(a,limits[0])
- elif limits[0]<>None and limits[1]<>None:
- mask = lowerfcn(a,limits[0])*upperfcn(a,limits[1])
- s = float(N.add.reduce(N.ravel(a*mask)))
- n = float(N.add.reduce(N.ravel(mask)))
- return s/n
-
-
- def atvar(a,limits=None,inclusive=(1,1)):
- """
-Returns the sample variance of values in an array, (i.e., using N-1),
-ignoring values strictly outside the sequence passed to 'limits'.
-Note: either limit in the sequence, or the value of limits itself,
-can be set to None. The inclusive list/tuple determines whether the lower
-and upper limiting bounds (respectively) are open/exclusive (0) or
-closed/inclusive (1). ASSUMES A FLAT ARRAY (OR ELSE PREFLATTENS).
-
-Usage: atvar(a,limits=None,inclusive=(1,1))
-"""
- a = a.astype(N.float_)
- if limits == None or limits == [None,None]:
- return avar(a)
- assert type(limits) in [ListType,TupleType,N.ndarray], "Wrong type for limits in atvar"
- if inclusive[0]: lowerfcn = N.greater_equal
- else: lowerfcn = N.greater
- if inclusive[1]: upperfcn = N.less_equal
- else: upperfcn = N.less
- if limits[0] > N.maximum.reduce(N.ravel(a)) or limits[1] < N.minimum.reduce(N.ravel(a)):
- raise ValueError, "No array values within given limits (atvar)."
- elif limits[0]==None and limits[1]<>None:
- mask = upperfcn(a,limits[1])
- elif limits[0]<>None and limits[1]==None:
- mask = lowerfcn(a,limits[0])
- elif limits[0]<>None and limits[1]<>None:
- mask = lowerfcn(a,limits[0])*upperfcn(a,limits[1])
-
- a = N.compress(mask,a) # squish out excluded values
- return avar(a)
-
-
- def atmin(a,lowerlimit=None,dimension=None,inclusive=1):
- """
-Returns the minimum value of a, along dimension, including only values less
-than (or equal to, if inclusive=1) lowerlimit. If the limit is set to None,
-all values in the array are used.
-
-Usage: atmin(a,lowerlimit=None,dimension=None,inclusive=1)
-"""
- if inclusive: lowerfcn = N.greater
- else: lowerfcn = N.greater_equal
- if dimension == None:
- a = N.ravel(a)
- dimension = 0
- if lowerlimit == None:
- lowerlimit = N.minimum.reduce(N.ravel(a))-11
- biggest = N.maximum.reduce(N.ravel(a))
- ta = N.where(lowerfcn(a,lowerlimit),a,biggest)
- return N.minimum.reduce(ta,dimension)
-
-
- def atmax(a,upperlimit,dimension=None,inclusive=1):
- """
-Returns the maximum value of a, along dimension, including only values greater
-than (or equal to, if inclusive=1) upperlimit. If the limit is set to None,
-a limit larger than the max value in the array is used.
-
-Usage: atmax(a,upperlimit,dimension=None,inclusive=1)
-"""
- if inclusive: upperfcn = N.less
- else: upperfcn = N.less_equal
- if dimension == None:
- a = N.ravel(a)
- dimension = 0
- if upperlimit == None:
- upperlimit = N.maximum.reduce(N.ravel(a))+1
- smallest = N.minimum.reduce(N.ravel(a))
- ta = N.where(upperfcn(a,upperlimit),a,smallest)
- return N.maximum.reduce(ta,dimension)
-
-
- def atstdev(a,limits=None,inclusive=(1,1)):
- """
-Returns the standard deviation of all values in an array, ignoring values
-strictly outside the sequence passed to 'limits'. Note: either limit
-in the sequence, or the value of limits itself, can be set to None. The
-inclusive list/tuple determines whether the lower and upper limiting bounds
-(respectively) are open/exclusive (0) or closed/inclusive (1).
-
-Usage: atstdev(a,limits=None,inclusive=(1,1))
-"""
- return N.sqrt(tvar(a,limits,inclusive))
-
-
- def atsem(a,limits=None,inclusive=(1,1)):
- """
-Returns the standard error of the mean for the values in an array,
-(i.e., using N for the denominator), ignoring values strictly outside
-the sequence passed to 'limits'. Note: either limit in the sequence,
-or the value of limits itself, can be set to None. The inclusive list/tuple
-determines whether the lower and upper limiting bounds (respectively) are
-open/exclusive (0) or closed/inclusive (1).
-
-Usage: atsem(a,limits=None,inclusive=(1,1))
-"""
- sd = tstdev(a,limits,inclusive)
- if limits == None or limits == [None,None]:
- n = float(len(N.ravel(a)))
- limits = [min(a)-1, max(a)+1]
- assert type(limits) in [ListType,TupleType,N.ndarray], "Wrong type for limits in atsem"
- if inclusive[0]: lowerfcn = N.greater_equal
- else: lowerfcn = N.greater
- if inclusive[1]: upperfcn = N.less_equal
- else: upperfcn = N.less
- if limits[0] > N.maximum.reduce(N.ravel(a)) or limits[1] < N.minimum.reduce(N.ravel(a)):
- raise ValueError, "No array values within given limits (atsem)."
- elif limits[0]==None and limits[1]<>None:
- mask = upperfcn(a,limits[1])
- elif limits[0]<>None and limits[1]==None:
- mask = lowerfcn(a,limits[0])
- elif limits[0]<>None and limits[1]<>None:
- mask = lowerfcn(a,limits[0])*upperfcn(a,limits[1])
- term1 = N.add.reduce(N.ravel(a*a*mask))
- n = float(N.add.reduce(N.ravel(mask)))
- return sd/math.sqrt(n)
-
-
-#####################################
-############ AMOMENTS #############
-#####################################
-
- def amoment(a,moment=1,dimension=None):
- """
-Calculates the nth moment about the mean for a sample (defaults to the
-1st moment). Generally used to calculate coefficients of skewness and
-kurtosis. Dimension can equal None (ravel array first), an integer
-(the dimension over which to operate), or a sequence (operate over
-multiple dimensions).
-
-Usage: amoment(a,moment=1,dimension=None)
-Returns: appropriate moment along given dimension
-"""
- if dimension == None:
- a = N.ravel(a)
- dimension = 0
- if moment == 1:
- return 0.0
- else:
- mn = amean(a,dimension,1) # 1=keepdims
- s = N.power((a-mn),moment)
- return amean(s,dimension)
-
-
- def avariation(a,dimension=None):
- """
-Returns the coefficient of variation, as defined in CRC Standard
-Probability and Statistics, p.6. Dimension can equal None (ravel array
-first), an integer (the dimension over which to operate), or a
-sequence (operate over multiple dimensions).
-
-Usage: avariation(a,dimension=None)
-"""
- return 100.0*asamplestdev(a,dimension)/amean(a,dimension)
-
-
- def askew(a,dimension=None):
- """
-Returns the skewness of a distribution (normal ==> 0.0; >0 means extra
-weight in left tail). Use askewtest() to see if it's close enough.
-Dimension can equal None (ravel array first), an integer (the
-dimension over which to operate), or a sequence (operate over multiple
-dimensions).
-
-Usage: askew(a, dimension=None)
-Returns: skew of vals in a along dimension, returning ZERO where all vals equal
-"""
- denom = N.power(amoment(a,2,dimension),1.5)
- zero = N.equal(denom,0)
- if type(denom) == N.ndarray and asum(zero) <> 0:
- print "Number of zeros in askew: ",asum(zero)
- denom = denom + zero # prevent divide-by-zero
- return N.where(zero, 0, amoment(a,3,dimension)/denom)
-
-
- def akurtosis(a,dimension=None):
- """
-Returns the kurtosis of a distribution (normal ==> 3.0; >3 means
-heavier in the tails, and usually more peaked). Use akurtosistest()
-to see if it's close enough. Dimension can equal None (ravel array
-first), an integer (the dimension over which to operate), or a
-sequence (operate over multiple dimensions).
-
-Usage: akurtosis(a,dimension=None)
-Returns: kurtosis of values in a along dimension, and ZERO where all vals equal
-"""
- denom = N.power(amoment(a,2,dimension),2)
- zero = N.equal(denom,0)
- if type(denom) == N.ndarray and asum(zero) <> 0:
- print "Number of zeros in akurtosis: ",asum(zero)
- denom = denom + zero # prevent divide-by-zero
- return N.where(zero,0,amoment(a,4,dimension)/denom)
-
-
- def adescribe(inarray,dimension=None):
- """
-Returns several descriptive statistics of the passed array. Dimension
-can equal None (ravel array first), an integer (the dimension over
-which to operate), or a sequence (operate over multiple dimensions).
-
-Usage: adescribe(inarray,dimension=None)
-Returns: n, (min,max), mean, standard deviation, skew, kurtosis
-"""
- if dimension == None:
- inarray = N.ravel(inarray)
- dimension = 0
- n = inarray.shape[dimension]
- mm = (N.minimum.reduce(inarray),N.maximum.reduce(inarray))
- m = amean(inarray,dimension)
- sd = astdev(inarray,dimension)
- skew = askew(inarray,dimension)
- kurt = akurtosis(inarray,dimension)
- return n, mm, m, sd, skew, kurt
-
-
-#####################################
-######## NORMALITY TESTS ##########
-#####################################
-
- def askewtest(a,dimension=None):
- """
-Tests whether the skew is significantly different from a normal
-distribution. Dimension can equal None (ravel array first), an
-integer (the dimension over which to operate), or a sequence (operate
-over multiple dimensions).
-
-Usage: askewtest(a,dimension=None)
-Returns: z-score and 2-tail z-probability
-"""
- if dimension == None:
- a = N.ravel(a)
- dimension = 0
- b2 = askew(a,dimension)
- n = float(a.shape[dimension])
- y = b2 * N.sqrt(((n+1)*(n+3)) / (6.0*(n-2)) )
- beta2 = ( 3.0*(n*n+27*n-70)*(n+1)*(n+3) ) / ( (n-2.0)*(n+5)*(n+7)*(n+9) )
- W2 = -1 + N.sqrt(2*(beta2-1))
- delta = 1/N.sqrt(N.log(N.sqrt(W2)))
- alpha = N.sqrt(2/(W2-1))
- y = N.where(y==0,1,y)
- Z = delta*N.log(y/alpha + N.sqrt((y/alpha)**2+1))
- return Z, (1.0-zprob(Z))*2
-
-
- def akurtosistest(a,dimension=None):
- """
-Tests whether a dataset has normal kurtosis (i.e.,
-kurtosis=3(n-1)/(n+1)) Valid only for n>20. Dimension can equal None
-(ravel array first), an integer (the dimension over which to operate),
-or a sequence (operate over multiple dimensions).
-
-Usage: akurtosistest(a,dimension=None)
-Returns: z-score and 2-tail z-probability, returns 0 for bad pixels
-"""
- if dimension == None:
- a = N.ravel(a)
- dimension = 0
- n = float(a.shape[dimension])
- if n<20:
- print "akurtosistest only valid for n>=20 ... continuing anyway, n=",n
- b2 = akurtosis(a,dimension)
- E = 3.0*(n-1) /(n+1)
- varb2 = 24.0*n*(n-2)*(n-3) / ((n+1)*(n+1)*(n+3)*(n+5))
- x = (b2-E)/N.sqrt(varb2)
- sqrtbeta1 = 6.0*(n*n-5*n+2)/((n+7)*(n+9)) * N.sqrt((6.0*(n+3)*(n+5))/
- (n*(n-2)*(n-3)))
- A = 6.0 + 8.0/sqrtbeta1 *(2.0/sqrtbeta1 + N.sqrt(1+4.0/(sqrtbeta1**2)))
- term1 = 1 -2/(9.0*A)
- denom = 1 +x*N.sqrt(2/(A-4.0))
- denom = N.where(N.less(denom,0), 99, denom)
- term2 = N.where(N.equal(denom,0), term1, N.power((1-2.0/A)/denom,1/3.0))
- Z = ( term1 - term2 ) / N.sqrt(2/(9.0*A))
- Z = N.where(N.equal(denom,99), 0, Z)
- return Z, (1.0-zprob(Z))*2
-
-
- def anormaltest(a,dimension=None):
- """
-Tests whether skew and/OR kurtosis of dataset differs from normal
-curve. Can operate over multiple dimensions. Dimension can equal
-None (ravel array first), an integer (the dimension over which to
-operate), or a sequence (operate over multiple dimensions).
-
-Usage: anormaltest(a,dimension=None)
-Returns: z-score and 2-tail probability
-"""
- if dimension == None:
- a = N.ravel(a)
- dimension = 0
- s,p = askewtest(a,dimension)
- k,p = akurtosistest(a,dimension)
- k2 = N.power(s,2) + N.power(k,2)
- return k2, achisqprob(k2,2)
-
-
-#####################################
-###### AFREQUENCY FUNCTIONS #######
-#####################################
-
- def aitemfreq(a):
- """
-Returns a 2D array of item frequencies. Column 1 contains item values,
-column 2 contains their respective counts. Assumes a 1D array is passed.
-@@@sorting OK?
-
-Usage: aitemfreq(a)
-Returns: a 2D frequency table (col [0:n-1]=scores, col n=frequencies)
-"""
- scores = pstat.aunique(a)
- scores = N.sort(scores)
- freq = N.zeros(len(scores))
- for i in range(len(scores)):
- freq[i] = N.add.reduce(N.equal(a,scores[i]))
- return N.array(pstat.aabut(scores, freq))
-
-
- def ascoreatpercentile (inarray, percent):
- """
-Usage: ascoreatpercentile(inarray,percent) 0<percent<100
-Returns: score at given percentile, relative to inarray distribution
-"""
- percent = percent / 100.0
- targetcf = percent*len(inarray)
- h, lrl, binsize, extras = histogram(inarray)
- cumhist = cumsum(h*1)
- for i in range(len(cumhist)):
- if cumhist[i] >= targetcf:
- break
- score = binsize * ((targetcf - cumhist[i-1]) / float(h[i])) + (lrl+binsize*i)
- return score
-
-
- def apercentileofscore (inarray,score,histbins=10,defaultlimits=None):
- """
-Note: result of this function depends on the values used to histogram
-the data(!).
-
-Usage: apercentileofscore(inarray,score,histbins=10,defaultlimits=None)
-Returns: percentile-position of score (0-100) relative to inarray
-"""
- h, lrl, binsize, extras = histogram(inarray,histbins,defaultlimits)
- cumhist = cumsum(h*1)
- i = int((score - lrl)/float(binsize))
- pct = (cumhist[i-1]+((score-(lrl+binsize*i))/float(binsize))*h[i])/float(len(inarray)) * 100
- return pct
-
-
- def ahistogram (inarray,numbins=10,defaultlimits=None,printextras=1):
- """
-Returns (i) an array of histogram bin counts, (ii) the smallest value
-of the histogram binning, and (iii) the bin width (the last 2 are not
-necessarily integers). Default number of bins is 10. Defaultlimits
-can be None (the routine picks bins spanning all the numbers in the
-inarray) or a 2-sequence (lowerlimit, upperlimit). Returns all of the
-following: array of bin values, lowerreallimit, binsize, extrapoints.
-
-Usage: ahistogram(inarray,numbins=10,defaultlimits=None,printextras=1)
-Returns: (array of bin counts, bin-minimum, min-width, #-points-outside-range)
-"""
- inarray = N.ravel(inarray) # flatten any >1D arrays
- if (defaultlimits <> None):
- lowerreallimit = defaultlimits[0]
- upperreallimit = defaultlimits[1]
- binsize = (upperreallimit-lowerreallimit) / float(numbins)
- else:
- Min = N.minimum.reduce(inarray)
- Max = N.maximum.reduce(inarray)
- estbinwidth = float(Max - Min)/float(numbins) + 1e-6
- binsize = (Max-Min+estbinwidth)/float(numbins)
- lowerreallimit = Min - binsize/2.0 #lower real limit,1st bin
- bins = N.zeros(numbins)
- extrapoints = 0
- for num in inarray:
- try:
- if (num-lowerreallimit) < 0:
- extrapoints = extrapoints + 1
- else:
- bintoincrement = int((num-lowerreallimit) / float(binsize))
- bins[bintoincrement] = bins[bintoincrement] + 1
- except: # point outside lower/upper limits
- extrapoints = extrapoints + 1
- if (extrapoints > 0 and printextras == 1):
- print '\nPoints outside given histogram range =',extrapoints
- return (bins, lowerreallimit, binsize, extrapoints)
-
-
- def acumfreq(a,numbins=10,defaultreallimits=None):
- """
-Returns a cumulative frequency histogram, using the histogram function.
-Defaultreallimits can be None (use all data), or a 2-sequence containing
-lower and upper limits on values to include.
-
-Usage: acumfreq(a,numbins=10,defaultreallimits=None)
-Returns: array of cumfreq bin values, lowerreallimit, binsize, extrapoints
-"""
- h,l,b,e = histogram(a,numbins,defaultreallimits)
- cumhist = cumsum(h*1)
- return cumhist,l,b,e
-
-
- def arelfreq(a,numbins=10,defaultreallimits=None):
- """
-Returns a relative frequency histogram, using the histogram function.
-Defaultreallimits can be None (use all data), or a 2-sequence containing
-lower and upper limits on values to include.
-
-Usage: arelfreq(a,numbins=10,defaultreallimits=None)
-Returns: array of cumfreq bin values, lowerreallimit, binsize, extrapoints
-"""
- h,l,b,e = histogram(a,numbins,defaultreallimits)
- h = N.array(h/float(a.shape[0]))
- return h,l,b,e
-
-
-#####################################
-###### AVARIABILITY FUNCTIONS #####
-#####################################
-
- def aobrientransform(*args):
- """
-Computes a transform on input data (any number of columns). Used to
-test for homogeneity of variance prior to running one-way stats. Each
-array in *args is one level of a factor. If an F_oneway() run on the
-transformed data and found significant, variances are unequal. From
-Maxwell and Delaney, p.112.
-
-Usage: aobrientransform(*args) *args = 1D arrays, one per level of factor
-Returns: transformed data for use in an ANOVA
-"""
- TINY = 1e-10
- k = len(args)
- n = N.zeros(k,N.float_)
- v = N.zeros(k,N.float_)
- m = N.zeros(k,N.float_)
- nargs = []
- for i in range(k):
- nargs.append(args[i].astype(N.float_))
- n[i] = float(len(nargs[i]))
- v[i] = var(nargs[i])
- m[i] = mean(nargs[i])
- for j in range(k):
- for i in range(n[j]):
- t1 = (n[j]-1.5)*n[j]*(nargs[j][i]-m[j])**2
- t2 = 0.5*v[j]*(n[j]-1.0)
- t3 = (n[j]-1.0)*(n[j]-2.0)
- nargs[j][i] = (t1-t2) / float(t3)
- check = 1
- for j in range(k):
- if v[j] - mean(nargs[j]) > TINY:
- check = 0
- if check <> 1:
- raise ValueError, 'Lack of convergence in obrientransform.'
- else:
- return N.array(nargs)
-
-
- def asamplevar (inarray,dimension=None,keepdims=0):
- """
-Returns the sample standard deviation of the values in the passed
-array (i.e., using N). Dimension can equal None (ravel array first),
-an integer (the dimension over which to operate), or a sequence
-(operate over multiple dimensions). Set keepdims=1 to return an array
-with the same number of dimensions as inarray.
-
-Usage: asamplevar(inarray,dimension=None,keepdims=0)
-"""
- if dimension == None:
- inarray = N.ravel(inarray)
- dimension = 0
- if dimension == 1:
- mn = amean(inarray,dimension)[:,N.NewAxis]
- else:
- mn = amean(inarray,dimension,keepdims=1)
- deviations = inarray - mn
- if type(dimension) == ListType:
- n = 1
- for d in dimension:
- n = n*inarray.shape[d]
- else:
- n = inarray.shape[dimension]
- svar = ass(deviations,dimension,keepdims) / float(n)
- return svar
-
-
- def asamplestdev (inarray, dimension=None, keepdims=0):
- """
-Returns the sample standard deviation of the values in the passed
-array (i.e., using N). Dimension can equal None (ravel array first),
-an integer (the dimension over which to operate), or a sequence
-(operate over multiple dimensions). Set keepdims=1 to return an array
-with the same number of dimensions as inarray.
-
-Usage: asamplestdev(inarray,dimension=None,keepdims=0)
-"""
- return N.sqrt(asamplevar(inarray,dimension,keepdims))
-
-
- def asignaltonoise(instack,dimension=0):
- """
-Calculates signal-to-noise. Dimension can equal None (ravel array
-first), an integer (the dimension over which to operate), or a
-sequence (operate over multiple dimensions).
-
-Usage: asignaltonoise(instack,dimension=0):
-Returns: array containing the value of (mean/stdev) along dimension,
- or 0 when stdev=0
-"""
- m = mean(instack,dimension)
- sd = stdev(instack,dimension)
- return N.where(sd==0,0,m/sd)
-
-
- def acov (x,y, dimension=None,keepdims=0):
- """
-Returns the estimated covariance of the values in the passed
-array (i.e., N-1). Dimension can equal None (ravel array first), an
-integer (the dimension over which to operate), or a sequence (operate
-over multiple dimensions). Set keepdims=1 to return an array with the
-same number of dimensions as inarray.
-
-Usage: acov(x,y,dimension=None,keepdims=0)
-"""
- if dimension == None:
- x = N.ravel(x)
- y = N.ravel(y)
- dimension = 0
- xmn = amean(x,dimension,1) # keepdims
- xdeviations = x - xmn
- ymn = amean(y,dimension,1) # keepdims
- ydeviations = y - ymn
- if type(dimension) == ListType:
- n = 1
- for d in dimension:
- n = n*x.shape[d]
- else:
- n = x.shape[dimension]
- covar = N.sum(xdeviations*ydeviations)/float(n-1)
- return covar
-
-
- def avar (inarray, dimension=None,keepdims=0):
- """
-Returns the estimated population variance of the values in the passed
-array (i.e., N-1). Dimension can equal None (ravel array first), an
-integer (the dimension over which to operate), or a sequence (operate
-over multiple dimensions). Set keepdims=1 to return an array with the
-same number of dimensions as inarray.
-
-Usage: avar(inarray,dimension=None,keepdims=0)
-"""
- if dimension == None:
- inarray = N.ravel(inarray)
- dimension = 0
- mn = amean(inarray,dimension,1)
- deviations = inarray - mn
- if type(dimension) == ListType:
- n = 1
- for d in dimension:
- n = n*inarray.shape[d]
- else:
- n = inarray.shape[dimension]
- var = ass(deviations,dimension,keepdims)/float(n-1)
- return var
-
-
- def astdev (inarray, dimension=None, keepdims=0):
- """
-Returns the estimated population standard deviation of the values in
-the passed array (i.e., N-1). Dimension can equal None (ravel array
-first), an integer (the dimension over which to operate), or a
-sequence (operate over multiple dimensions). Set keepdims=1 to return
-an array with the same number of dimensions as inarray.
-
-Usage: astdev(inarray,dimension=None,keepdims=0)
-"""
- return N.sqrt(avar(inarray,dimension,keepdims))
-
-
- def asterr (inarray, dimension=None, keepdims=0):
- """
-Returns the estimated population standard error of the values in the
-passed array (i.e., N-1). Dimension can equal None (ravel array
-first), an integer (the dimension over which to operate), or a
-sequence (operate over multiple dimensions). Set keepdims=1 to return
-an array with the same number of dimensions as inarray.
-
-Usage: asterr(inarray,dimension=None,keepdims=0)
-"""
- if dimension == None:
- inarray = N.ravel(inarray)
- dimension = 0
- return astdev(inarray,dimension,keepdims) / float(N.sqrt(inarray.shape[dimension]))
-
-
- def asem (inarray, dimension=None, keepdims=0):
- """
-Returns the standard error of the mean (i.e., using N) of the values
-in the passed array. Dimension can equal None (ravel array first), an
-integer (the dimension over which to operate), or a sequence (operate
-over multiple dimensions). Set keepdims=1 to return an array with the
-same number of dimensions as inarray.
-
-Usage: asem(inarray,dimension=None, keepdims=0)
-"""
- if dimension == None:
- inarray = N.ravel(inarray)
- dimension = 0
- if type(dimension) == ListType:
- n = 1
- for d in dimension:
- n = n*inarray.shape[d]
- else:
- n = inarray.shape[dimension]
- s = asamplestdev(inarray,dimension,keepdims) / N.sqrt(n-1)
- return s
-
-
- def az (a, score):
- """
-Returns the z-score of a given input score, given thearray from which
-that score came. Not appropriate for population calculations, nor for
-arrays > 1D.
-
-Usage: az(a, score)
-"""
- z = (score-amean(a)) / asamplestdev(a)
- return z
-
-
- def azs (a):
- """
-Returns a 1D array of z-scores, one for each score in the passed array,
-computed relative to the passed array.
-
-Usage: azs(a)
-"""
- zscores = []
- for item in a:
- zscores.append(z(a,item))
- return N.array(zscores)
-
-
- def azmap (scores, compare, dimension=0):
- """
-Returns an array of z-scores the shape of scores (e.g., [x,y]), compared to
-array passed to compare (e.g., [time,x,y]). Assumes collapsing over dim 0
-of the compare array.
-
-Usage: azs(scores, compare, dimension=0)
-"""
- mns = amean(compare,dimension)
- sstd = asamplestdev(compare,0)
- return (scores - mns) / sstd
-
-
-#####################################
-####### ATRIMMING FUNCTIONS #######
-#####################################
-
-## deleted around() as it's in numpy now
-
- def athreshold(a,threshmin=None,threshmax=None,newval=0):
- """
-Like Numeric.clip() except that values <threshmid or >threshmax are replaced
-by newval instead of by threshmin/threshmax (respectively).
-
-Usage: athreshold(a,threshmin=None,threshmax=None,newval=0)
-Returns: a, with values <threshmin or >threshmax replaced with newval
-"""
- mask = N.zeros(a.shape)
- if threshmin <> None:
- mask = mask + N.where(a<threshmin,1,0)
- if threshmax <> None:
- mask = mask + N.where(a>threshmax,1,0)
- mask = N.clip(mask,0,1)
- return N.where(mask,newval,a)
-
-
- def atrimboth (a,proportiontocut):
- """
-Slices off the passed proportion of items from BOTH ends of the passed
-array (i.e., with proportiontocut=0.1, slices 'leftmost' 10% AND
-'rightmost' 10% of scores. You must pre-sort the array if you want
-"proper" trimming. Slices off LESS if proportion results in a
-non-integer slice index (i.e., conservatively slices off
-proportiontocut).
-
-Usage: atrimboth (a,proportiontocut)
-Returns: trimmed version of array a
-"""
- lowercut = int(proportiontocut*len(a))
- uppercut = len(a) - lowercut
- return a[lowercut:uppercut]
-
-
- def atrim1 (a,proportiontocut,tail='right'):
- """
-Slices off the passed proportion of items from ONE end of the passed
-array (i.e., if proportiontocut=0.1, slices off 'leftmost' or 'rightmost'
-10% of scores). Slices off LESS if proportion results in a non-integer
-slice index (i.e., conservatively slices off proportiontocut).
-
-Usage: atrim1(a,proportiontocut,tail='right') or set tail='left'
-Returns: trimmed version of array a
-"""
- if string.lower(tail) == 'right':
- lowercut = 0
- uppercut = len(a) - int(proportiontocut*len(a))
- elif string.lower(tail) == 'left':
- lowercut = int(proportiontocut*len(a))
- uppercut = len(a)
- return a[lowercut:uppercut]
-
-
-#####################################
-##### ACORRELATION FUNCTIONS ######
-#####################################
-
- def acovariance(X):
- """
-Computes the covariance matrix of a matrix X. Requires a 2D matrix input.
-
-Usage: acovariance(X)
-Returns: covariance matrix of X
-"""
- if len(X.shape) <> 2:
- raise TypeError, "acovariance requires 2D matrices"
- n = X.shape[0]
- mX = amean(X,0)
- return N.dot(N.transpose(X),X) / float(n) - N.multiply.outer(mX,mX)
-
-
- def acorrelation(X):
- """
-Computes the correlation matrix of a matrix X. Requires a 2D matrix input.
-
-Usage: acorrelation(X)
-Returns: correlation matrix of X
-"""
- C = acovariance(X)
- V = N.diagonal(C)
- return C / N.sqrt(N.multiply.outer(V,V))
-
-
- def apaired(x,y):
- """
-Interactively determines the type of data in x and y, and then runs the
-appropriated statistic for paired group data.
-
-Usage: apaired(x,y) x,y = the two arrays of values to be compared
-Returns: appropriate statistic name, value, and probability
-"""
- samples = ''
- while samples not in ['i','r','I','R','c','C']:
- print '\nIndependent or related samples, or correlation (i,r,c): ',
- samples = raw_input()
-
- if samples in ['i','I','r','R']:
- print '\nComparing variances ...',
-# USE O'BRIEN'S TEST FOR HOMOGENEITY OF VARIANCE, Maxwell & delaney, p.112
- r = obrientransform(x,y)
- f,p = F_oneway(pstat.colex(r,0),pstat.colex(r,1))
- if p<0.05:
- vartype='unequal, p='+str(round(p,4))
- else:
- vartype='equal'
- print vartype
- if samples in ['i','I']:
- if vartype[0]=='e':
- t,p = ttest_ind(x,y,None,0)
- print '\nIndependent samples t-test: ', round(t,4),round(p,4)
- else:
- if len(x)>20 or len(y)>20:
- z,p = ranksums(x,y)
- print '\nRank Sums test (NONparametric, n>20): ', round(z,4),round(p,4)
- else:
- u,p = mannwhitneyu(x,y)
- print '\nMann-Whitney U-test (NONparametric, ns<20): ', round(u,4),round(p,4)
-
- else: # RELATED SAMPLES
- if vartype[0]=='e':
- t,p = ttest_rel(x,y,0)
- print '\nRelated samples t-test: ', round(t,4),round(p,4)
- else:
- t,p = ranksums(x,y)
- print '\nWilcoxon T-test (NONparametric): ', round(t,4),round(p,4)
- else: # CORRELATION ANALYSIS
- corrtype = ''
- while corrtype not in ['c','C','r','R','d','D']:
- print '\nIs the data Continuous, Ranked, or Dichotomous (c,r,d): ',
- corrtype = raw_input()
- if corrtype in ['c','C']:
- m,b,r,p,see = linregress(x,y)
- print '\nLinear regression for continuous variables ...'
- lol = [['Slope','Intercept','r','Prob','SEestimate'],[round(m,4),round(b,4),round(r,4),round(p,4),round(see,4)]]
- pstat.printcc(lol)
- elif corrtype in ['r','R']:
- r,p = spearmanr(x,y)
- print '\nCorrelation for ranked variables ...'
- print "Spearman's r: ",round(r,4),round(p,4)
- else: # DICHOTOMOUS
- r,p = pointbiserialr(x,y)
- print '\nAssuming x contains a dichotomous variable ...'
- print 'Point Biserial r: ',round(r,4),round(p,4)
- print '\n\n'
- return None
-
-
- def dices(x,y):
- """
-Calculates Dice's coefficient ... (2*number of common terms)/(number of terms in x +
-number of terms in y). Returns a value between 0 (orthogonal) and 1.
-
-Usage: dices(x,y)
-"""
- import sets
- x = sets.Set(x)
- y = sets.Set(y)
- common = len(x.intersection(y))
- total = float(len(x) + len(y))
- return 2*common/total
-
-
- def icc(x,y=None,verbose=0):
- """
-Calculates intraclass correlation coefficients using simple, Type I sums of squares.
-If only one variable is passed, assumed it's an Nx2 matrix
-
-Usage: icc(x,y=None,verbose=0)
-Returns: icc rho, prob ####PROB IS A GUESS BASED ON PEARSON
-"""
- TINY = 1.0e-20
- if y:
- all = N.concatenate([x,y],0)
- else:
- all = x+0
- x = all[:,0]
- y = all[:,1]
- totalss = ass(all-mean(all))
- pairmeans = (x+y)/2.
- withinss = ass(x-pairmeans) + ass(y-pairmeans)
- withindf = float(len(x))
- betwdf = float(len(x)-1)
- withinms = withinss / withindf
- betweenms = (totalss-withinss) / betwdf
- rho = (betweenms-withinms)/(withinms+betweenms)
- t = rho*math.sqrt(betwdf/((1.0-rho+TINY)*(1.0+rho+TINY)))
- prob = abetai(0.5*betwdf,0.5,betwdf/(betwdf+t*t),verbose)
- return rho, prob
-
-
- def alincc(x,y):
- """
-Calculates Lin's concordance correlation coefficient.
-
-Usage: alincc(x,y) where x, y are equal-length arrays
-Returns: Lin's CC
-"""
- x = N.ravel(x)
- y = N.ravel(y)
- covar = acov(x,y)*(len(x)-1)/float(len(x)) # correct denom to n
- xvar = avar(x)*(len(x)-1)/float(len(x)) # correct denom to n
- yvar = avar(y)*(len(y)-1)/float(len(y)) # correct denom to n
- lincc = (2 * covar) / ((xvar+yvar) +((amean(x)-amean(y))**2))
- return lincc
-
-
- def apearsonr(x,y,verbose=1):
- """
-Calculates a Pearson correlation coefficient and returns p. Taken
-from Heiman's Basic Statistics for the Behav. Sci (2nd), p.195.
-
-Usage: apearsonr(x,y,verbose=1) where x,y are equal length arrays
-Returns: Pearson's r, two-tailed p-value
-"""
- TINY = 1.0e-20
- n = len(x)
- xmean = amean(x)
- ymean = amean(y)
- r_num = n*(N.add.reduce(x*y)) - N.add.reduce(x)*N.add.reduce(y)
- r_den = math.sqrt((n*ass(x) - asquare_of_sums(x))*(n*ass(y)-asquare_of_sums(y)))
- r = (r_num / r_den)
- df = n-2
- t = r*math.sqrt(df/((1.0-r+TINY)*(1.0+r+TINY)))
- prob = abetai(0.5*df,0.5,df/(df+t*t),verbose)
- return r,prob
-
-
- def aspearmanr(x,y):
- """
-Calculates a Spearman rank-order correlation coefficient. Taken
-from Heiman's Basic Statistics for the Behav. Sci (1st), p.192.
-
-Usage: aspearmanr(x,y) where x,y are equal-length arrays
-Returns: Spearman's r, two-tailed p-value
-"""
- TINY = 1e-30
- n = len(x)
- rankx = rankdata(x)
- ranky = rankdata(y)
- dsq = N.add.reduce((rankx-ranky)**2)
- rs = 1 - 6*dsq / float(n*(n**2-1))
- t = rs * math.sqrt((n-2) / ((rs+1.0)*(1.0-rs)))
- df = n-2
- probrs = abetai(0.5*df,0.5,df/(df+t*t))
-# probability values for rs are from part 2 of the spearman function in
-# Numerical Recipies, p.510. They close to tables, but not exact.(?)
- return rs, probrs
-
-
- def apointbiserialr(x,y):
- """
-Calculates a point-biserial correlation coefficient and the associated
-probability value. Taken from Heiman's Basic Statistics for the Behav.
-Sci (1st), p.194.
-
-Usage: apointbiserialr(x,y) where x,y are equal length arrays
-Returns: Point-biserial r, two-tailed p-value
-"""
- TINY = 1e-30
- categories = pstat.aunique(x)
- data = pstat.aabut(x,y)
- if len(categories) <> 2:
- raise ValueError, "Exactly 2 categories required (in x) for pointbiserialr()."
- else: # there are 2 categories, continue
- codemap = pstat.aabut(categories,N.arange(2))
- recoded = pstat.arecode(data,codemap,0)
- x = pstat.alinexand(data,0,categories[0])
- y = pstat.alinexand(data,0,categories[1])
- xmean = amean(pstat.acolex(x,1))
- ymean = amean(pstat.acolex(y,1))
- n = len(data)
- adjust = math.sqrt((len(x)/float(n))*(len(y)/float(n)))
- rpb = (ymean - xmean)/asamplestdev(pstat.acolex(data,1))*adjust
- df = n-2
- t = rpb*math.sqrt(df/((1.0-rpb+TINY)*(1.0+rpb+TINY)))
- prob = abetai(0.5*df,0.5,df/(df+t*t))
- return rpb, prob
-
-
- def akendalltau(x,y):
- """
-Calculates Kendall's tau ... correlation of ordinal data. Adapted
-from function kendl1 in Numerical Recipies. Needs good test-cases.@@@
-
-Usage: akendalltau(x,y)
-Returns: Kendall's tau, two-tailed p-value
-"""
- n1 = 0
- n2 = 0
- iss = 0
- for j in range(len(x)-1):
- for k in range(j,len(y)):
- a1 = x[j] - x[k]
- a2 = y[j] - y[k]
- aa = a1 * a2
- if (aa): # neither array has a tie
- n1 = n1 + 1
- n2 = n2 + 1
- if aa > 0:
- iss = iss + 1
- else:
- iss = iss -1
- else:
- if (a1):
- n1 = n1 + 1
- else:
- n2 = n2 + 1
- tau = iss / math.sqrt(n1*n2)
- svar = (4.0*len(x)+10.0) / (9.0*len(x)*(len(x)-1))
- z = tau / math.sqrt(svar)
- prob = erfcc(abs(z)/1.4142136)
- return tau, prob
-
-
- def alinregress(*args):
- """
-Calculates a regression line on two arrays, x and y, corresponding to x,y
-pairs. If a single 2D array is passed, alinregress finds dim with 2 levels
-and splits data into x,y pairs along that dim.
-
-Usage: alinregress(*args) args=2 equal-length arrays, or one 2D array
-Returns: slope, intercept, r, two-tailed prob, sterr-of-the-estimate, n
-"""
- TINY = 1.0e-20
- if len(args) == 1: # more than 1D array?
- args = args[0]
- if len(args) == 2:
- x = args[0]
- y = args[1]
- else:
- x = args[:,0]
- y = args[:,1]
- else:
- x = args[0]
- y = args[1]
- n = len(x)
- xmean = amean(x)
- ymean = amean(y)
- r_num = n*(N.add.reduce(x*y)) - N.add.reduce(x)*N.add.reduce(y)
- r_den = math.sqrt((n*ass(x) - asquare_of_sums(x))*(n*ass(y)-asquare_of_sums(y)))
- r = r_num / r_den
- z = 0.5*math.log((1.0+r+TINY)/(1.0-r+TINY))
- df = n-2
- t = r*math.sqrt(df/((1.0-r+TINY)*(1.0+r+TINY)))
- prob = abetai(0.5*df,0.5,df/(df+t*t))
- slope = r_num / (float(n)*ass(x) - asquare_of_sums(x))
- intercept = ymean - slope*xmean
- sterrest = math.sqrt(1-r*r)*asamplestdev(y)
- return slope, intercept, r, prob, sterrest, n
-
- def amasslinregress(*args):
- """
-Calculates a regression line on one 1D array (x) and one N-D array (y).
-
-Returns: slope, intercept, r, two-tailed prob, sterr-of-the-estimate, n
-"""
- TINY = 1.0e-20
- if len(args) == 1: # more than 1D array?
- args = args[0]
- if len(args) == 2:
- x = N.ravel(args[0])
- y = args[1]
- else:
- x = N.ravel(args[:,0])
- y = args[:,1]
- else:
- x = args[0]
- y = args[1]
- x = x.astype(N.float_)
- y = y.astype(N.float_)
- n = len(x)
- xmean = amean(x)
- ymean = amean(y,0)
- shp = N.ones(len(y.shape))
- shp[0] = len(x)
- x.shape = shp
- print x.shape, y.shape
- r_num = n*(N.add.reduce(x*y,0)) - N.add.reduce(x)*N.add.reduce(y,0)
- r_den = N.sqrt((n*ass(x) - asquare_of_sums(x))*(n*ass(y,0)-asquare_of_sums(y,0)))
- zerodivproblem = N.equal(r_den,0)
- r_den = N.where(zerodivproblem,1,r_den) # avoid zero-division in 1st place
- r = r_num / r_den # need to do this nicely for matrix division
- r = N.where(zerodivproblem,0.0,r)
- z = 0.5*N.log((1.0+r+TINY)/(1.0-r+TINY))
- df = n-2
- t = r*N.sqrt(df/((1.0-r+TINY)*(1.0+r+TINY)))
- prob = abetai(0.5*df,0.5,df/(df+t*t))
-
- ss = float(n)*ass(x)-asquare_of_sums(x)
- s_den = N.where(ss==0,1,ss) # avoid zero-division in 1st place
- slope = r_num / s_den
- intercept = ymean - slope*xmean
- sterrest = N.sqrt(1-r*r)*asamplestdev(y,0)
- return slope, intercept, r, prob, sterrest, n
-
-
-#####################################
-##### AINFERENTIAL STATISTICS #####
-#####################################
-
- def attest_1samp(a,popmean,printit=0,name='Sample',writemode='a'):
- """
-Calculates the t-obtained for the independent samples T-test on ONE group
-of scores a, given a population mean. If printit=1, results are printed
-to the screen. If printit='filename', the results are output to 'filename'
-using the given writemode (default=append). Returns t-value, and prob.
-
-Usage: attest_1samp(a,popmean,Name='Sample',printit=0,writemode='a')
-Returns: t-value, two-tailed prob
-"""
- if type(a) != N.ndarray:
- a = N.array(a)
- x = amean(a)
- v = avar(a)
- n = len(a)
- df = n-1
- svar = ((n-1)*v) / float(df)
- t = (x-popmean)/math.sqrt(svar*(1.0/n))
- prob = abetai(0.5*df,0.5,df/(df+t*t))
-
- if printit <> 0:
- statname = 'Single-sample T-test.'
- outputpairedstats(printit,writemode,
- 'Population','--',popmean,0,0,0,
- name,n,x,v,N.minimum.reduce(N.ravel(a)),
- N.maximum.reduce(N.ravel(a)),
- statname,t,prob)
- return t,prob
-
-
- def attest_ind (a, b, dimension=None, printit=0, name1='Samp1', name2='Samp2',writemode='a'):
- """
-Calculates the t-obtained T-test on TWO INDEPENDENT samples of scores
-a, and b. From Numerical Recipies, p.483. If printit=1, results are
-printed to the screen. If printit='filename', the results are output
-to 'filename' using the given writemode (default=append). Dimension
-can equal None (ravel array first), or an integer (the dimension over
-which to operate on a and b).
-
-Usage: attest_ind (a,b,dimension=None,printit=0,
- Name1='Samp1',Name2='Samp2',writemode='a')
-Returns: t-value, two-tailed p-value
-"""
- if dimension == None:
- a = N.ravel(a)
- b = N.ravel(b)
- dimension = 0
- x1 = amean(a,dimension)
- x2 = amean(b,dimension)
- v1 = avar(a,dimension)
- v2 = avar(b,dimension)
- n1 = a.shape[dimension]
- n2 = b.shape[dimension]
- df = n1+n2-2
- svar = ((n1-1)*v1+(n2-1)*v2) / float(df)
- zerodivproblem = N.equal(svar,0)
- svar = N.where(zerodivproblem,1,svar) # avoid zero-division in 1st place
- t = (x1-x2)/N.sqrt(svar*(1.0/n1 + 1.0/n2)) # N-D COMPUTATION HERE!!!!!!
- t = N.where(zerodivproblem,1.0,t) # replace NaN/wrong t-values with 1.0
- probs = abetai(0.5*df,0.5,float(df)/(df+t*t))
-
- if type(t) == N.ndarray:
- probs = N.reshape(probs,t.shape)
- if probs.shape == (1,):
- probs = probs[0]
-
- if printit <> 0:
- if type(t) == N.ndarray:
- t = t[0]
- if type(probs) == N.ndarray:
- probs = probs[0]
- statname = 'Independent samples T-test.'
- outputpairedstats(printit,writemode,
- name1,n1,x1,v1,N.minimum.reduce(N.ravel(a)),
- N.maximum.reduce(N.ravel(a)),
- name2,n2,x2,v2,N.minimum.reduce(N.ravel(b)),
- N.maximum.reduce(N.ravel(b)),
- statname,t,probs)
- return
- return t, probs
-
- def ap2t(pval,df):
- """
-Tries to compute a t-value from a p-value (or pval array) and associated df.
-SLOW for large numbers of elements(!) as it re-computes p-values 20 times
-(smaller step-sizes) at which point it decides it's done. Keeps the signs
-of the input array. Returns 1000 (or -1000) if t>100.
-
-Usage: ap2t(pval,df)
-Returns: an array of t-values with the shape of pval
- """
- pval = N.array(pval)
- signs = N.sign(pval)
- pval = abs(pval)
- t = N.ones(pval.shape,N.float_)*50
- step = N.ones(pval.shape,N.float_)*25
- print "Initial ap2t() prob calc"
- prob = abetai(0.5*df,0.5,float(df)/(df+t*t))
- print 'ap2t() iter: ',
- for i in range(10):
- print i,' ',
- t = N.where(pval<prob,t+step,t-step)
- prob = abetai(0.5*df,0.5,float(df)/(df+t*t))
- step = step/2
- print
- # since this is an ugly hack, we get ugly boundaries
- t = N.where(t>99.9,1000,t) # hit upper-boundary
- t = t+signs
- return t #, prob, pval
-
-
- def attest_rel (a,b,dimension=None,printit=0,name1='Samp1',name2='Samp2',writemode='a'):
- """
-Calculates the t-obtained T-test on TWO RELATED samples of scores, a
-and b. From Numerical Recipies, p.483. If printit=1, results are
-printed to the screen. If printit='filename', the results are output
-to 'filename' using the given writemode (default=append). Dimension
-can equal None (ravel array first), or an integer (the dimension over
-which to operate on a and b).
-
-Usage: attest_rel(a,b,dimension=None,printit=0,
- name1='Samp1',name2='Samp2',writemode='a')
-Returns: t-value, two-tailed p-value
-"""
- if dimension == None:
- a = N.ravel(a)
- b = N.ravel(b)
- dimension = 0
- if len(a)<>len(b):
- raise ValueError, 'Unequal length arrays.'
- x1 = amean(a,dimension)
- x2 = amean(b,dimension)
- v1 = avar(a,dimension)
- v2 = avar(b,dimension)
- n = a.shape[dimension]
- df = float(n-1)
- d = (a-b).astype('d')
-
- denom = N.sqrt((n*N.add.reduce(d*d,dimension) - N.add.reduce(d,dimension)**2) /df)
- zerodivproblem = N.equal(denom,0)
- denom = N.where(zerodivproblem,1,denom) # avoid zero-division in 1st place
- t = N.add.reduce(d,dimension) / denom # N-D COMPUTATION HERE!!!!!!
- t = N.where(zerodivproblem,1.0,t) # replace NaN/wrong t-values with 1.0
- probs = abetai(0.5*df,0.5,float(df)/(df+t*t))
- if type(t) == N.ndarray:
- probs = N.reshape(probs,t.shape)
- if probs.shape == (1,):
- probs = probs[0]
-
- if printit <> 0:
- statname = 'Related samples T-test.'
- outputpairedstats(printit,writemode,
- name1,n,x1,v1,N.minimum.reduce(N.ravel(a)),
- N.maximum.reduce(N.ravel(a)),
- name2,n,x2,v2,N.minimum.reduce(N.ravel(b)),
- N.maximum.reduce(N.ravel(b)),
- statname,t,probs)
- return
- return t, probs
-
-
- def achisquare(f_obs,f_exp=None):
- """
-Calculates a one-way chi square for array of observed frequencies and returns
-the result. If no expected frequencies are given, the total N is assumed to
-be equally distributed across all groups.
-@@@NOT RIGHT??
-
-Usage: achisquare(f_obs, f_exp=None) f_obs = array of observed cell freq.
-Returns: chisquare-statistic, associated p-value
-"""
-
- k = len(f_obs)
- if f_exp == None:
- f_exp = N.array([sum(f_obs)/float(k)] * len(f_obs),N.float_)
- f_exp = f_exp.astype(N.float_)
- chisq = N.add.reduce((f_obs-f_exp)**2 / f_exp)
- return chisq, achisqprob(chisq, k-1)
-
-
- def aks_2samp (data1,data2):
- """
-Computes the Kolmogorov-Smirnof statistic on 2 samples. Modified from
-Numerical Recipies in C, page 493. Returns KS D-value, prob. Not ufunc-
-like.
-
-Usage: aks_2samp(data1,data2) where data1 and data2 are 1D arrays
-Returns: KS D-value, p-value
-"""
- j1 = 0 # N.zeros(data1.shape[1:]) TRIED TO MAKE THIS UFUNC-LIKE
- j2 = 0 # N.zeros(data2.shape[1:])
- fn1 = 0.0 # N.zeros(data1.shape[1:],N.float_)
- fn2 = 0.0 # N.zeros(data2.shape[1:],N.float_)
- n1 = data1.shape[0]
- n2 = data2.shape[0]
- en1 = n1*1
- en2 = n2*1
- d = N.zeros(data1.shape[1:],N.float_)
- data1 = N.sort(data1,0)
- data2 = N.sort(data2,0)
- while j1 < n1 and j2 < n2:
- d1=data1[j1]
- d2=data2[j2]
- if d1 <= d2:
- fn1 = (j1)/float(en1)
- j1 = j1 + 1
- if d2 <= d1:
- fn2 = (j2)/float(en2)
- j2 = j2 + 1
- dt = (fn2-fn1)
- if abs(dt) > abs(d):
- d = dt
-# try:
- en = math.sqrt(en1*en2/float(en1+en2))
- prob = aksprob((en+0.12+0.11/en)*N.fabs(d))
-# except:
-# prob = 1.0
- return d, prob
-
-
- def amannwhitneyu(x,y):
- """
-Calculates a Mann-Whitney U statistic on the provided scores and
-returns the result. Use only when the n in each condition is < 20 and
-you have 2 independent samples of ranks. REMEMBER: Mann-Whitney U is
-significant if the u-obtained is LESS THAN or equal to the critical
-value of U.
-
-Usage: amannwhitneyu(x,y) where x,y are arrays of values for 2 conditions
-Returns: u-statistic, one-tailed p-value (i.e., p(z(U)))
-"""
- n1 = len(x)
- n2 = len(y)
- ranked = rankdata(N.concatenate((x,y)))
- rankx = ranked[0:n1] # get the x-ranks
- ranky = ranked[n1:] # the rest are y-ranks
- u1 = n1*n2 + (n1*(n1+1))/2.0 - sum(rankx) # calc U for x
- u2 = n1*n2 - u1 # remainder is U for y
- bigu = max(u1,u2)
- smallu = min(u1,u2)
- proportion = bigu/float(n1*n2)
- T = math.sqrt(tiecorrect(ranked)) # correction factor for tied scores
- if T == 0:
- raise ValueError, 'All numbers are identical in amannwhitneyu'
- sd = math.sqrt(T*n1*n2*(n1+n2+1)/12.0)
- z = abs((bigu-n1*n2/2.0) / sd) # normal approximation for prob calc
- return smallu, 1.0 - azprob(z), proportion
-
-
- def atiecorrect(rankvals):
- """
-Tie-corrector for ties in Mann Whitney U and Kruskal Wallis H tests.
-See Siegel, S. (1956) Nonparametric Statistics for the Behavioral
-Sciences. New York: McGraw-Hill. Code adapted from |Stat rankind.c
-code.
-
-Usage: atiecorrect(rankvals)
-Returns: T correction factor for U or H
-"""
- sorted,posn = ashellsort(N.array(rankvals))
- n = len(sorted)
- T = 0.0
- i = 0
- while (i<n-1):
- if sorted[i] == sorted[i+1]:
- nties = 1
- while (i<n-1) and (sorted[i] == sorted[i+1]):
- nties = nties +1
- i = i +1
- T = T + nties**3 - nties
- i = i+1
- T = T / float(n**3-n)
- return 1.0 - T
-
-
- def aranksums(x,y):
- """
-Calculates the rank sums statistic on the provided scores and returns
-the result.
-
-Usage: aranksums(x,y) where x,y are arrays of values for 2 conditions
-Returns: z-statistic, two-tailed p-value
-"""
- n1 = len(x)
- n2 = len(y)
- alldata = N.concatenate((x,y))
- ranked = arankdata(alldata)
- x = ranked[:n1]
- y = ranked[n1:]
- s = sum(x)
- expected = n1*(n1+n2+1) / 2.0
- z = (s - expected) / math.sqrt(n1*n2*(n1+n2+1)/12.0)
- prob = 2*(1.0 - azprob(abs(z)))
- return z, prob
-
-
- def awilcoxont(x,y):
- """
-Calculates the Wilcoxon T-test for related samples and returns the
-result. A non-parametric T-test.
-
-Usage: awilcoxont(x,y) where x,y are equal-length arrays for 2 conditions
-Returns: t-statistic, two-tailed p-value
-"""
- if len(x) <> len(y):
- raise ValueError, 'Unequal N in awilcoxont. Aborting.'
- d = x-y
- d = N.compress(N.not_equal(d,0),d) # Keep all non-zero differences
- count = len(d)
- absd = abs(d)
- absranked = arankdata(absd)
- r_plus = 0.0
- r_minus = 0.0
- for i in range(len(absd)):
- if d[i] < 0:
- r_minus = r_minus + absranked[i]
- else:
- r_plus = r_plus + absranked[i]
- wt = min(r_plus, r_minus)
- mn = count * (count+1) * 0.25
- se = math.sqrt(count*(count+1)*(2.0*count+1.0)/24.0)
- z = math.fabs(wt-mn) / se
- z = math.fabs(wt-mn) / se
- prob = 2*(1.0 -zprob(abs(z)))
- return wt, prob
-
-
- def akruskalwallish(*args):
- """
-The Kruskal-Wallis H-test is a non-parametric ANOVA for 3 or more
-groups, requiring at least 5 subjects in each group. This function
-calculates the Kruskal-Wallis H and associated p-value for 3 or more
-independent samples.
-
-Usage: akruskalwallish(*args) args are separate arrays for 3+ conditions
-Returns: H-statistic (corrected for ties), associated p-value
-"""
- assert len(args) == 3, "Need at least 3 groups in stats.akruskalwallish()"
- args = list(args)
- n = [0]*len(args)
- n = map(len,args)
- all = []
- for i in range(len(args)):
- all = all + args[i].tolist()
- ranked = rankdata(all)
- T = tiecorrect(ranked)
- for i in range(len(args)):
- args[i] = ranked[0:n[i]]
- del ranked[0:n[i]]
- rsums = []
- for i in range(len(args)):
- rsums.append(sum(args[i])**2)
- rsums[i] = rsums[i] / float(n[i])
- ssbn = sum(rsums)
- totaln = sum(n)
- h = 12.0 / (totaln*(totaln+1)) * ssbn - 3*(totaln+1)
- df = len(args) - 1
- if T == 0:
- raise ValueError, 'All numbers are identical in akruskalwallish'
- h = h / float(T)
- return h, chisqprob(h,df)
-
-
- def afriedmanchisquare(*args):
- """
-Friedman Chi-Square is a non-parametric, one-way within-subjects
-ANOVA. This function calculates the Friedman Chi-square test for
-repeated measures and returns the result, along with the associated
-probability value. It assumes 3 or more repeated measures. Only 3
-levels requires a minimum of 10 subjects in the study. Four levels
-requires 5 subjects per level(??).
-
-Usage: afriedmanchisquare(*args) args are separate arrays for 2+ conditions
-Returns: chi-square statistic, associated p-value
-"""
- k = len(args)
- if k < 3:
- raise ValueError, '\nLess than 3 levels. Friedman test not appropriate.\n'
- n = len(args[0])
- data = apply(pstat.aabut,args)
- data = data.astype(N.float_)
- for i in range(len(data)):
- data[i] = arankdata(data[i])
- ssbn = asum(asum(args,1)**2)
- chisq = 12.0 / (k*n*(k+1)) * ssbn - 3*n*(k+1)
- return chisq, achisqprob(chisq,k-1)
-
-
-#####################################
-#### APROBABILITY CALCULATIONS ####
-#####################################
-
- def achisqprob(chisq,df):
- """
-Returns the (1-tail) probability value associated with the provided chi-square
-value and df. Heavily modified from chisq.c in Gary Perlman's |Stat. Can
-handle multiple dimensions.
-
-Usage: achisqprob(chisq,df) chisq=chisquare stat., df=degrees of freedom
-"""
- BIG = 200.0
- def ex(x):
- BIG = 200.0
- exponents = N.where(N.less(x,-BIG),-BIG,x)
- return N.exp(exponents)
-
- if type(chisq) == N.ndarray:
- arrayflag = 1
- else:
- arrayflag = 0
- chisq = N.array([chisq])
- if df < 1:
- return N.ones(chisq.shape,N.float)
- probs = N.zeros(chisq.shape,N.float_)
- probs = N.where(N.less_equal(chisq,0),1.0,probs) # set prob=1 for chisq<0
- a = 0.5 * chisq
- if df > 1:
- y = ex(-a)
- if df%2 == 0:
- even = 1
- s = y*1
- s2 = s*1
- else:
- even = 0
- s = 2.0 * azprob(-N.sqrt(chisq))
- s2 = s*1
- if (df > 2):
- chisq = 0.5 * (df - 1.0)
- if even:
- z = N.ones(probs.shape,N.float_)
- else:
- z = 0.5 *N.ones(probs.shape,N.float_)
- if even:
- e = N.zeros(probs.shape,N.float_)
- else:
- e = N.log(N.sqrt(N.pi)) *N.ones(probs.shape,N.float_)
- c = N.log(a)
- mask = N.zeros(probs.shape)
- a_big = N.greater(a,BIG)
- a_big_frozen = -1 *N.ones(probs.shape,N.float_)
- totalelements = N.multiply.reduce(N.array(probs.shape))
- while asum(mask)<>totalelements:
- e = N.log(z) + e
- s = s + ex(c*z-a-e)
- z = z + 1.0
-# print z, e, s
- newmask = N.greater(z,chisq)
- a_big_frozen = N.where(newmask*N.equal(mask,0)*a_big, s, a_big_frozen)
- mask = N.clip(newmask+mask,0,1)
- if even:
- z = N.ones(probs.shape,N.float_)
- e = N.ones(probs.shape,N.float_)
- else:
- z = 0.5 *N.ones(probs.shape,N.float_)
- e = 1.0 / N.sqrt(N.pi) / N.sqrt(a) * N.ones(probs.shape,N.float_)
- c = 0.0
- mask = N.zeros(probs.shape)
- a_notbig_frozen = -1 *N.ones(probs.shape,N.float_)
- while asum(mask)<>totalelements:
- e = e * (a/z.astype(N.float_))
- c = c + e
- z = z + 1.0
-# print '#2', z, e, c, s, c*y+s2
- newmask = N.greater(z,chisq)
- a_notbig_frozen = N.where(newmask*N.equal(mask,0)*(1-a_big),
- c*y+s2, a_notbig_frozen)
- mask = N.clip(newmask+mask,0,1)
- probs = N.where(N.equal(probs,1),1,
- N.where(N.greater(a,BIG),a_big_frozen,a_notbig_frozen))
- return probs
- else:
- return s
-
-
- def aerfcc(x):
- """
-Returns the complementary error function erfc(x) with fractional error
-everywhere less than 1.2e-7. Adapted from Numerical Recipies. Can
-handle multiple dimensions.
-
-Usage: aerfcc(x)
-"""
- z = abs(x)
- t = 1.0 / (1.0+0.5*z)
- ans = t * N.exp(-z*z-1.26551223 + t*(1.00002368+t*(0.37409196+t*(0.09678418+t*(-0.18628806+t*(0.27886807+t*(-1.13520398+t*(1.48851587+t*(-0.82215223+t*0.17087277)))))))))
- return N.where(N.greater_equal(x,0), ans, 2.0-ans)
-
-
- def azprob(z):
- """
-Returns the area under the normal curve 'to the left of' the given z value.
-Thus,
- for z<0, zprob(z) = 1-tail probability
- for z>0, 1.0-zprob(z) = 1-tail probability
- for any z, 2.0*(1.0-zprob(abs(z))) = 2-tail probability
-Adapted from z.c in Gary Perlman's |Stat. Can handle multiple dimensions.
-
-Usage: azprob(z) where z is a z-value
-"""
- def yfunc(y):
- x = (((((((((((((-0.000045255659 * y
- +0.000152529290) * y -0.000019538132) * y
- -0.000676904986) * y +0.001390604284) * y
- -0.000794620820) * y -0.002034254874) * y
- +0.006549791214) * y -0.010557625006) * y
- +0.011630447319) * y -0.009279453341) * y
- +0.005353579108) * y -0.002141268741) * y
- +0.000535310849) * y +0.999936657524
- return x
-
- def wfunc(w):
- x = ((((((((0.000124818987 * w
- -0.001075204047) * w +0.005198775019) * w
- -0.019198292004) * w +0.059054035642) * w
- -0.151968751364) * w +0.319152932694) * w
- -0.531923007300) * w +0.797884560593) * N.sqrt(w) * 2.0
- return x
-
- Z_MAX = 6.0 # maximum meaningful z-value
- x = N.zeros(z.shape,N.float_) # initialize
- y = 0.5 * N.fabs(z)
- x = N.where(N.less(y,1.0),wfunc(y*y),yfunc(y-2.0)) # get x's
- x = N.where(N.greater(y,Z_MAX*0.5),1.0,x) # kill those with big Z
- prob = N.where(N.greater(z,0),(x+1)*0.5,(1-x)*0.5)
- return prob
-
-
- def aksprob(alam):
- """
-Returns the probability value for a K-S statistic computed via ks_2samp.
-Adapted from Numerical Recipies. Can handle multiple dimensions.
-
-Usage: aksprob(alam)
-"""
- if type(alam) == N.ndarray:
- frozen = -1 *N.ones(alam.shape,N.float64)
- alam = alam.astype(N.float64)
- arrayflag = 1
- else:
- frozen = N.array(-1.)
- alam = N.array(alam,N.float64)
- arrayflag = 1
- mask = N.zeros(alam.shape)
- fac = 2.0 *N.ones(alam.shape,N.float_)
- sum = N.zeros(alam.shape,N.float_)
- termbf = N.zeros(alam.shape,N.float_)
- a2 = N.array(-2.0*alam*alam,N.float64)
- totalelements = N.multiply.reduce(N.array(mask.shape))
- for j in range(1,201):
- if asum(mask) == totalelements:
- break
- exponents = (a2*j*j)
- overflowmask = N.less(exponents,-746)
- frozen = N.where(overflowmask,0,frozen)
- mask = mask+overflowmask
- term = fac*N.exp(exponents)
- sum = sum + term
- newmask = N.where(N.less_equal(abs(term),(0.001*termbf)) +
- N.less(abs(term),1.0e-8*sum), 1, 0)
- frozen = N.where(newmask*N.equal(mask,0), sum, frozen)
- mask = N.clip(mask+newmask,0,1)
- fac = -fac
- termbf = abs(term)
- if arrayflag:
- return N.where(N.equal(frozen,-1), 1.0, frozen) # 1.0 if doesn't converge
- else:
- return N.where(N.equal(frozen,-1), 1.0, frozen)[0] # 1.0 if doesn't converge
-
-
- def afprob (dfnum, dfden, F):
- """
-Returns the 1-tailed significance level (p-value) of an F statistic
-given the degrees of freedom for the numerator (dfR-dfF) and the degrees
-of freedom for the denominator (dfF). Can handle multiple dims for F.
-
-Usage: afprob(dfnum, dfden, F) where usually dfnum=dfbn, dfden=dfwn
-"""
- if type(F) == N.ndarray:
- return abetai(0.5*dfden, 0.5*dfnum, dfden/(1.0*dfden+dfnum*F))
- else:
- return abetai(0.5*dfden, 0.5*dfnum, dfden/float(dfden+dfnum*F))
-
-
- def abetacf(a,b,x,verbose=1):
- """
-Evaluates the continued fraction form of the incomplete Beta function,
-betai. (Adapted from: Numerical Recipies in C.) Can handle multiple
-dimensions for x.
-
-Usage: abetacf(a,b,x,verbose=1)
-"""
- ITMAX = 200
- EPS = 3.0e-7
-
- arrayflag = 1
- if type(x) == N.ndarray:
- frozen = N.ones(x.shape,N.float_) *-1 #start out w/ -1s, should replace all
- else:
- arrayflag = 0
- frozen = N.array([-1])
- x = N.array([x])
- mask = N.zeros(x.shape)
- bm = az = am = 1.0
- qab = a+b
- qap = a+1.0
- qam = a-1.0
- bz = 1.0-qab*x/qap
- for i in range(ITMAX+1):
- if N.sum(N.ravel(N.equal(frozen,-1)))==0:
- break
- em = float(i+1)
- tem = em + em
- d = em*(b-em)*x/((qam+tem)*(a+tem))
- ap = az + d*am
- bp = bz+d*bm
- d = -(a+em)*(qab+em)*x/((qap+tem)*(a+tem))
- app = ap+d*az
- bpp = bp+d*bz
- aold = az*1
- am = ap/bpp
- bm = bp/bpp
- az = app/bpp
- bz = 1.0
- newmask = N.less(abs(az-aold),EPS*abs(az))
- frozen = N.where(newmask*N.equal(mask,0), az, frozen)
- mask = N.clip(mask+newmask,0,1)
- noconverge = asum(N.equal(frozen,-1))
- if noconverge <> 0 and verbose:
- print 'a or b too big, or ITMAX too small in Betacf for ',noconverge,' elements'
- if arrayflag:
- return frozen
- else:
- return frozen[0]
-
-
- def agammln(xx):
- """
-Returns the gamma function of xx.
- Gamma(z) = Integral(0,infinity) of t^(z-1)exp(-t) dt.
-Adapted from: Numerical Recipies in C. Can handle multiple dims ... but
-probably doesn't normally have to.
-
-Usage: agammln(xx)
-"""
- coeff = [76.18009173, -86.50532033, 24.01409822, -1.231739516,
- 0.120858003e-2, -0.536382e-5]
- x = xx - 1.0
- tmp = x + 5.5
- tmp = tmp - (x+0.5)*N.log(tmp)
- ser = 1.0
- for j in range(len(coeff)):
- x = x + 1
- ser = ser + coeff[j]/x
- return -tmp + N.log(2.50662827465*ser)
-
-
- def abetai(a,b,x,verbose=1):
- """
-Returns the incomplete beta function:
-
- I-sub-x(a,b) = 1/B(a,b)*(Integral(0,x) of t^(a-1)(1-t)^(b-1) dt)
-
-where a,b>0 and B(a,b) = G(a)*G(b)/(G(a+b)) where G(a) is the gamma
-function of a. The continued fraction formulation is implemented
-here, using the betacf function. (Adapted from: Numerical Recipies in
-C.) Can handle multiple dimensions.
-
-Usage: abetai(a,b,x,verbose=1)
-"""
- TINY = 1e-15
- if type(a) == N.ndarray:
- if asum(N.less(x,0)+N.greater(x,1)) <> 0:
- raise ValueError, 'Bad x in abetai'
- x = N.where(N.equal(x,0),TINY,x)
- x = N.where(N.equal(x,1.0),1-TINY,x)
-
- bt = N.where(N.equal(x,0)+N.equal(x,1), 0, -1)
- exponents = ( gammln(a+b)-gammln(a)-gammln(b)+a*N.log(x)+b*
- N.log(1.0-x) )
- # 746 (below) is the MAX POSSIBLE BEFORE OVERFLOW
- exponents = N.where(N.less(exponents,-740),-740,exponents)
- bt = N.exp(exponents)
- if type(x) == N.ndarray:
- ans = N.where(N.less(x,(a+1)/(a+b+2.0)),
- bt*abetacf(a,b,x,verbose)/float(a),
- 1.0-bt*abetacf(b,a,1.0-x,verbose)/float(b))
- else:
- if x<(a+1)/(a+b+2.0):
- ans = bt*abetacf(a,b,x,verbose)/float(a)
- else:
- ans = 1.0-bt*abetacf(b,a,1.0-x,verbose)/float(b)
- return ans
-
-
-#####################################
-####### AANOVA CALCULATIONS #######
-#####################################
-
- import numpy.linalg, operator
- LA = numpy.linalg
-
- def aglm(data,para):
- """
-Calculates a linear model fit ... anova/ancova/lin-regress/t-test/etc. Taken
-from:
- Peterson et al. Statistical limitations in functional neuroimaging
- I. Non-inferential methods and statistical models. Phil Trans Royal Soc
- Lond B 354: 1239-1260.
-
-Usage: aglm(data,para)
-Returns: statistic, p-value ???
-"""
- if len(para) <> len(data):
- print "data and para must be same length in aglm"
- return
- n = len(para)
- p = pstat.aunique(para)
- x = N.zeros((n,len(p))) # design matrix
- for l in range(len(p)):
- x[:,l] = N.equal(para,p[l])
- b = N.dot(N.dot(LA.inv(N.dot(N.transpose(x),x)), # i.e., b=inv(X'X)X'Y
- N.transpose(x)),
- data)
- diffs = (data - N.dot(x,b))
- s_sq = 1./(n-len(p)) * N.dot(N.transpose(diffs), diffs)
-
- if len(p) == 2: # ttest_ind
- c = N.array([1,-1])
- df = n-2
- fact = asum(1.0/asum(x,0)) # i.e., 1/n1 + 1/n2 + 1/n3 ...
- t = N.dot(c,b) / N.sqrt(s_sq*fact)
- probs = abetai(0.5*df,0.5,float(df)/(df+t*t))
- return t, probs
-
-
- def aF_oneway(*args):
- """
-Performs a 1-way ANOVA, returning an F-value and probability given
-any number of groups. From Heiman, pp.394-7.
-
-Usage: aF_oneway (*args) where *args is 2 or more arrays, one per
- treatment group
-Returns: f-value, probability
-"""
- na = len(args) # ANOVA on 'na' groups, each in it's own array
- means = [0]*na
- vars = [0]*na
- ns = [0]*na
- alldata = []
- tmp = map(N.array,args)
- means = map(amean,tmp)
- vars = map(avar,tmp)
- ns = map(len,args)
- alldata = N.concatenate(args)
- bign = len(alldata)
- sstot = ass(alldata)-(asquare_of_sums(alldata)/float(bign))
- ssbn = 0
- for a in args:
- ssbn = ssbn + asquare_of_sums(N.array(a))/float(len(a))
- ssbn = ssbn - (asquare_of_sums(alldata)/float(bign))
- sswn = sstot-ssbn
- dfbn = na-1
- dfwn = bign - na
- msb = ssbn/float(dfbn)
- msw = sswn/float(dfwn)
- f = msb/msw
- prob = fprob(dfbn,dfwn,f)
- return f, prob
-
-
- def aF_value (ER,EF,dfR,dfF):
- """
-Returns an F-statistic given the following:
- ER = error associated with the null hypothesis (the Restricted model)
- EF = error associated with the alternate hypothesis (the Full model)
- dfR = degrees of freedom the Restricted model
- dfF = degrees of freedom associated with the Restricted model
-"""
- return ((ER-EF)/float(dfR-dfF) / (EF/float(dfF)))
-
-
- def outputfstats(Enum, Eden, dfnum, dfden, f, prob):
- Enum = round(Enum,3)
- Eden = round(Eden,3)
- dfnum = round(Enum,3)
- dfden = round(dfden,3)
- f = round(f,3)
- prob = round(prob,3)
- suffix = '' # for *s after the p-value
- if prob < 0.001: suffix = ' ***'
- elif prob < 0.01: suffix = ' **'
- elif prob < 0.05: suffix = ' *'
- title = [['EF/ER','DF','Mean Square','F-value','prob','']]
- lofl = title+[[Enum, dfnum, round(Enum/float(dfnum),3), f, prob, suffix],
- [Eden, dfden, round(Eden/float(dfden),3),'','','']]
- pstat.printcc(lofl)
- return
-
-
- def F_value_multivariate(ER, EF, dfnum, dfden):
- """
-Returns an F-statistic given the following:
- ER = error associated with the null hypothesis (the Restricted model)
- EF = error associated with the alternate hypothesis (the Full model)
- dfR = degrees of freedom the Restricted model
- dfF = degrees of freedom associated with the Restricted model
-where ER and EF are matrices from a multivariate F calculation.
-"""
- if type(ER) in [IntType, FloatType]:
- ER = N.array([[ER]])
- if type(EF) in [IntType, FloatType]:
- EF = N.array([[EF]])
- n_um = (LA.det(ER) - LA.det(EF)) / float(dfnum)
- d_en = LA.det(EF) / float(dfden)
- return n_um / d_en
-
-
-#####################################
-####### ASUPPORT FUNCTIONS ########
-#####################################
-
- def asign(a):
- """
-Usage: asign(a)
-Returns: array shape of a, with -1 where a<0 and +1 where a>=0
-"""
- a = N.asarray(a)
- if ((type(a) == type(1.4)) or (type(a) == type(1))):
- return a-a-N.less(a,0)+N.greater(a,0)
- else:
- return N.zeros(N.shape(a))-N.less(a,0)+N.greater(a,0)
-
-
- def asum (a, dimension=None,keepdims=0):
- """
-An alternative to the Numeric.add.reduce function, which allows one to
-(1) collapse over multiple dimensions at once, and/or (2) to retain
-all dimensions in the original array (squashing one down to size.
-Dimension can equal None (ravel array first), an integer (the
-dimension over which to operate), or a sequence (operate over multiple
-dimensions). If keepdims=1, the resulting array will have as many
-dimensions as the input array.
-
-Usage: asum(a, dimension=None, keepdims=0)
-Returns: array summed along 'dimension'(s), same _number_ of dims if keepdims=1
-"""
- if type(a) == N.ndarray and a.dtype in [N.int_, N.short, N.ubyte]:
- a = a.astype(N.float_)
- if dimension == None:
- s = N.sum(N.ravel(a))
- elif type(dimension) in [IntType,FloatType]:
- s = N.add.reduce(a, dimension)
- if keepdims == 1:
- shp = list(a.shape)
- shp[dimension] = 1
- s = N.reshape(s,shp)
- else: # must be a SEQUENCE of dims to sum over
- dims = list(dimension)
- dims.sort()
- dims.reverse()
- s = a *1.0
- for dim in dims:
- s = N.add.reduce(s,dim)
- if keepdims == 1:
- shp = list(a.shape)
- for dim in dims:
- shp[dim] = 1
- s = N.reshape(s,shp)
- return s
-
-
- def acumsum (a,dimension=None):
- """
-Returns an array consisting of the cumulative sum of the items in the
-passed array. Dimension can equal None (ravel array first), an
-integer (the dimension over which to operate), or a sequence (operate
-over multiple dimensions, but this last one just barely makes sense).
-
-Usage: acumsum(a,dimension=None)
-"""
- if dimension == None:
- a = N.ravel(a)
- dimension = 0
- if type(dimension) in [ListType, TupleType, N.ndarray]:
- dimension = list(dimension)
- dimension.sort()
- dimension.reverse()
- for d in dimension:
- a = N.add.accumulate(a,d)
- return a
- else:
- return N.add.accumulate(a,dimension)
-
-
- def ass(inarray, dimension=None, keepdims=0):
- """
-Squares each value in the passed array, adds these squares & returns
-the result. Unfortunate function name. :-) Defaults to ALL values in
-the array. Dimension can equal None (ravel array first), an integer
-(the dimension over which to operate), or a sequence (operate over
-multiple dimensions). Set keepdims=1 to maintain the original number
-of dimensions.
-
-Usage: ass(inarray, dimension=None, keepdims=0)
-Returns: sum-along-'dimension' for (inarray*inarray)
-"""
- if dimension == None:
- inarray = N.ravel(inarray)
- dimension = 0
- return asum(inarray*inarray,dimension,keepdims)
-
-
- def asummult (array1,array2,dimension=None,keepdims=0):
- """
-Multiplies elements in array1 and array2, element by element, and
-returns the sum (along 'dimension') of all resulting multiplications.
-Dimension can equal None (ravel array first), an integer (the
-dimension over which to operate), or a sequence (operate over multiple
-dimensions). A trivial function, but included for completeness.
-
-Usage: asummult(array1,array2,dimension=None,keepdims=0)
-"""
- if dimension == None:
- array1 = N.ravel(array1)
- array2 = N.ravel(array2)
- dimension = 0
- return asum(array1*array2,dimension,keepdims)
-
-
- def asquare_of_sums(inarray, dimension=None, keepdims=0):
- """
-Adds the values in the passed array, squares that sum, and returns the
-result. Dimension can equal None (ravel array first), an integer (the
-dimension over which to operate), or a sequence (operate over multiple
-dimensions). If keepdims=1, the returned array will have the same
-NUMBER of dimensions as the original.
-
-Usage: asquare_of_sums(inarray, dimension=None, keepdims=0)
-Returns: the square of the sum over dim(s) in dimension
-"""
- if dimension == None:
- inarray = N.ravel(inarray)
- dimension = 0
- s = asum(inarray,dimension,keepdims)
- if type(s) == N.ndarray:
- return s.astype(N.float_)*s
- else:
- return float(s)*s
-
-
- def asumdiffsquared(a,b, dimension=None, keepdims=0):
- """
-Takes pairwise differences of the values in arrays a and b, squares
-these differences, and returns the sum of these squares. Dimension
-can equal None (ravel array first), an integer (the dimension over
-which to operate), or a sequence (operate over multiple dimensions).
-keepdims=1 means the return shape = len(a.shape) = len(b.shape)
-
-Usage: asumdiffsquared(a,b)
-Returns: sum[ravel(a-b)**2]
-"""
- if dimension == None:
- inarray = N.ravel(a)
- dimension = 0
- return asum((a-b)**2,dimension,keepdims)
-
-
- def ashellsort(inarray):
- """
-Shellsort algorithm. Sorts a 1D-array.
-
-Usage: ashellsort(inarray)
-Returns: sorted-inarray, sorting-index-vector (for original array)
-"""
- n = len(inarray)
- svec = inarray *1.0
- ivec = range(n)
- gap = n/2 # integer division needed
- while gap >0:
- for i in range(gap,n):
- for j in range(i-gap,-1,-gap):
- while j>=0 and svec[j]>svec[j+gap]:
- temp = svec[j]
- svec[j] = svec[j+gap]
- svec[j+gap] = temp
- itemp = ivec[j]
- ivec[j] = ivec[j+gap]
- ivec[j+gap] = itemp
- gap = gap / 2 # integer division needed
-# svec is now sorted input vector, ivec has the order svec[i] = vec[ivec[i]]
- return svec, ivec
-
-
- def arankdata(inarray):
- """
-Ranks the data in inarray, dealing with ties appropritely. Assumes
-a 1D inarray. Adapted from Gary Perlman's |Stat ranksort.
-
-Usage: arankdata(inarray)
-Returns: array of length equal to inarray, containing rank scores
-"""
- n = len(inarray)
- svec, ivec = ashellsort(inarray)
- sumranks = 0
- dupcount = 0
- newarray = N.zeros(n,N.float_)
- for i in range(n):
- sumranks = sumranks + i
- dupcount = dupcount + 1
- if i==n-1 or svec[i] <> svec[i+1]:
- averank = sumranks / float(dupcount) + 1
- for j in range(i-dupcount+1,i+1):
- newarray[ivec[j]] = averank
- sumranks = 0
- dupcount = 0
- return newarray
-
-
- def afindwithin(data):
- """
-Returns a binary vector, 1=within-subject factor, 0=between. Input
-equals the entire data array (i.e., column 1=random factor, last
-column = measured values.
-
-Usage: afindwithin(data) data in |Stat format
-"""
- numfact = len(data[0])-2
- withinvec = [0]*numfact
- for col in range(1,numfact+1):
- rows = pstat.linexand(data,col,pstat.unique(pstat.colex(data,1))[0]) # get 1 level of this factor
- if len(pstat.unique(pstat.colex(rows,0))) < len(rows): # if fewer subjects than scores on this factor
- withinvec[col-1] = 1
- return withinvec
-
-
- #########################################################
- #########################################################
- ###### RE-DEFINE DISPATCHES TO INCLUDE ARRAYS #########
- #########################################################
- #########################################################
-
-## CENTRAL TENDENCY:
- geometricmean = Dispatch ( (lgeometricmean, (ListType, TupleType)),
- (ageometricmean, (N.ndarray,)) )
- harmonicmean = Dispatch ( (lharmonicmean, (ListType, TupleType)),
- (aharmonicmean, (N.ndarray,)) )
- mean = Dispatch ( (lmean, (ListType, TupleType)),
- (amean, (N.ndarray,)) )
- median = Dispatch ( (lmedian, (ListType, TupleType)),
- (amedian, (N.ndarray,)) )
- medianscore = Dispatch ( (lmedianscore, (ListType, TupleType)),
- (amedianscore, (N.ndarray,)) )
- mode = Dispatch ( (lmode, (ListType, TupleType)),
- (amode, (N.ndarray,)) )
- tmean = Dispatch ( (atmean, (N.ndarray,)) )
- tvar = Dispatch ( (atvar, (N.ndarray,)) )
- tstdev = Dispatch ( (atstdev, (N.ndarray,)) )
- tsem = Dispatch ( (atsem, (N.ndarray,)) )
-
-## VARIATION:
- moment = Dispatch ( (lmoment, (ListType, TupleType)),
- (amoment, (N.ndarray,)) )
- variation = Dispatch ( (lvariation, (ListType, TupleType)),
- (avariation, (N.ndarray,)) )
- skew = Dispatch ( (lskew, (ListType, TupleType)),
- (askew, (N.ndarray,)) )
- kurtosis = Dispatch ( (lkurtosis, (ListType, TupleType)),
- (akurtosis, (N.ndarray,)) )
- describe = Dispatch ( (ldescribe, (ListType, TupleType)),
- (adescribe, (N.ndarray,)) )
-
-## DISTRIBUTION TESTS
-
- skewtest = Dispatch ( (askewtest, (ListType, TupleType)),
- (askewtest, (N.ndarray,)) )
- kurtosistest = Dispatch ( (akurtosistest, (ListType, TupleType)),
- (akurtosistest, (N.ndarray,)) )
- normaltest = Dispatch ( (anormaltest, (ListType, TupleType)),
- (anormaltest, (N.ndarray,)) )
-
-## FREQUENCY STATS:
- itemfreq = Dispatch ( (litemfreq, (ListType, TupleType)),
- (aitemfreq, (N.ndarray,)) )
- scoreatpercentile = Dispatch ( (lscoreatpercentile, (ListType, TupleType)),
- (ascoreatpercentile, (N.ndarray,)) )
- percentileofscore = Dispatch ( (lpercentileofscore, (ListType, TupleType)),
- (apercentileofscore, (N.ndarray,)) )
- histogram = Dispatch ( (lhistogram, (ListType, TupleType)),
- (ahistogram, (N.ndarray,)) )
- cumfreq = Dispatch ( (lcumfreq, (ListType, TupleType)),
- (acumfreq, (N.ndarray,)) )
- relfreq = Dispatch ( (lrelfreq, (ListType, TupleType)),
- (arelfreq, (N.ndarray,)) )
-
-## VARIABILITY:
- obrientransform = Dispatch ( (lobrientransform, (ListType, TupleType)),
- (aobrientransform, (N.ndarray,)) )
- samplevar = Dispatch ( (lsamplevar, (ListType, TupleType)),
- (asamplevar, (N.ndarray,)) )
- samplestdev = Dispatch ( (lsamplestdev, (ListType, TupleType)),
- (asamplestdev, (N.ndarray,)) )
- signaltonoise = Dispatch( (asignaltonoise, (N.ndarray,)),)
- var = Dispatch ( (lvar, (ListType, TupleType)),
- (avar, (N.ndarray,)) )
- stdev = Dispatch ( (lstdev, (ListType, TupleType)),
- (astdev, (N.ndarray,)) )
- sterr = Dispatch ( (lsterr, (ListType, TupleType)),
- (asterr, (N.ndarray,)) )
- sem = Dispatch ( (lsem, (ListType, TupleType)),
- (asem, (N.ndarray,)) )
- z = Dispatch ( (lz, (ListType, TupleType)),
- (az, (N.ndarray,)) )
- zs = Dispatch ( (lzs, (ListType, TupleType)),
- (azs, (N.ndarray,)) )
-
-## TRIMMING FCNS:
- threshold = Dispatch( (athreshold, (N.ndarray,)),)
- trimboth = Dispatch ( (ltrimboth, (ListType, TupleType)),
- (atrimboth, (N.ndarray,)) )
- trim1 = Dispatch ( (ltrim1, (ListType, TupleType)),
- (atrim1, (N.ndarray,)) )
-
-## CORRELATION FCNS:
- paired = Dispatch ( (lpaired, (ListType, TupleType)),
- (apaired, (N.ndarray,)) )
- lincc = Dispatch ( (llincc, (ListType, TupleType)),
- (alincc, (N.ndarray,)) )
- pearsonr = Dispatch ( (lpearsonr, (ListType, TupleType)),
- (apearsonr, (N.ndarray,)) )
- spearmanr = Dispatch ( (lspearmanr, (ListType, TupleType)),
- (aspearmanr, (N.ndarray,)) )
- pointbiserialr = Dispatch ( (lpointbiserialr, (ListType, TupleType)),
- (apointbiserialr, (N.ndarray,)) )
- kendalltau = Dispatch ( (lkendalltau, (ListType, TupleType)),
- (akendalltau, (N.ndarray,)) )
- linregress = Dispatch ( (llinregress, (ListType, TupleType)),
- (alinregress, (N.ndarray,)) )
-
-## INFERENTIAL STATS:
- ttest_1samp = Dispatch ( (lttest_1samp, (ListType, TupleType)),
- (attest_1samp, (N.ndarray,)) )
- ttest_ind = Dispatch ( (lttest_ind, (ListType, TupleType)),
- (attest_ind, (N.ndarray,)) )
- ttest_rel = Dispatch ( (lttest_rel, (ListType, TupleType)),
- (attest_rel, (N.ndarray,)) )
- chisquare = Dispatch ( (lchisquare, (ListType, TupleType)),
- (achisquare, (N.ndarray,)) )
- ks_2samp = Dispatch ( (lks_2samp, (ListType, TupleType)),
- (aks_2samp, (N.ndarray,)) )
- mannwhitneyu = Dispatch ( (lmannwhitneyu, (ListType, TupleType)),
- (amannwhitneyu, (N.ndarray,)) )
- tiecorrect = Dispatch ( (ltiecorrect, (ListType, TupleType)),
- (atiecorrect, (N.ndarray,)) )
- ranksums = Dispatch ( (lranksums, (ListType, TupleType)),
- (aranksums, (N.ndarray,)) )
- wilcoxont = Dispatch ( (lwilcoxont, (ListType, TupleType)),
- (awilcoxont, (N.ndarray,)) )
- kruskalwallish = Dispatch ( (lkruskalwallish, (ListType, TupleType)),
- (akruskalwallish, (N.ndarray,)) )
- friedmanchisquare = Dispatch ( (lfriedmanchisquare, (ListType, TupleType)),
- (afriedmanchisquare, (N.ndarray,)) )
-
-## PROBABILITY CALCS:
- chisqprob = Dispatch ( (lchisqprob, (IntType, FloatType)),
- (achisqprob, (N.ndarray,)) )
- zprob = Dispatch ( (lzprob, (IntType, FloatType)),
- (azprob, (N.ndarray,)) )
- ksprob = Dispatch ( (lksprob, (IntType, FloatType)),
- (aksprob, (N.ndarray,)) )
- fprob = Dispatch ( (lfprob, (IntType, FloatType)),
- (afprob, (N.ndarray,)) )
- betacf = Dispatch ( (lbetacf, (IntType, FloatType)),
- (abetacf, (N.ndarray,)) )
- betai = Dispatch ( (lbetai, (IntType, FloatType)),
- (abetai, (N.ndarray,)) )
- erfcc = Dispatch ( (lerfcc, (IntType, FloatType)),
- (aerfcc, (N.ndarray,)) )
- gammln = Dispatch ( (lgammln, (IntType, FloatType)),
- (agammln, (N.ndarray,)) )
-
-## ANOVA FUNCTIONS:
- F_oneway = Dispatch ( (lF_oneway, (ListType, TupleType)),
- (aF_oneway, (N.ndarray,)) )
- F_value = Dispatch ( (lF_value, (ListType, TupleType)),
- (aF_value, (N.ndarray,)) )
-
-## SUPPORT FUNCTIONS:
- incr = Dispatch ( (lincr, (ListType, TupleType, N.ndarray)), )
- sum = Dispatch ( (lsum, (ListType, TupleType)),
- (asum, (N.ndarray,)) )
- cumsum = Dispatch ( (lcumsum, (ListType, TupleType)),
- (acumsum, (N.ndarray,)) )
- ss = Dispatch ( (lss, (ListType, TupleType)),
- (ass, (N.ndarray,)) )
- summult = Dispatch ( (lsummult, (ListType, TupleType)),
- (asummult, (N.ndarray,)) )
- square_of_sums = Dispatch ( (lsquare_of_sums, (ListType, TupleType)),
- (asquare_of_sums, (N.ndarray,)) )
- sumdiffsquared = Dispatch ( (lsumdiffsquared, (ListType, TupleType)),
- (asumdiffsquared, (N.ndarray,)) )
- shellsort = Dispatch ( (lshellsort, (ListType, TupleType)),
- (ashellsort, (N.ndarray,)) )
- rankdata = Dispatch ( (lrankdata, (ListType, TupleType)),
- (arankdata, (N.ndarray,)) )
- findwithin = Dispatch ( (lfindwithin, (ListType, TupleType)),
- (afindwithin, (N.ndarray,)) )
-
-###################### END OF NUMERIC FUNCTION BLOCK #####################
-
-###################### END OF STATISTICAL FUNCTIONS ######################
-
-except ImportError:
- pass
diff --git a/v14/utils/tabulator.py b/v14/utils/tabulator.py
deleted file mode 100644
index f75419ab..00000000
--- a/v14/utils/tabulator.py
+++ /dev/null
@@ -1,1125 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2011 Google Inc. All Rights Reserved.
-
-"""Table generating, analyzing and printing functions.
-
-This defines several classes that are used to generate, analyze and print
-tables.
-
-Example usage:
-
- from utils import tabulator
-
- data = [["benchmark1", "33", "44"],["benchmark2", "44", "33"]]
- tabulator.GetSimpleTable(data)
-
-You could also use it to generate more complex tables with analysis such as
-p-values, custom colors, etc. Tables are generated by TableGenerator and
-analyzed/formatted by TableFormatter. TableFormatter can take in a list of
-columns with custom result computation and coloring, and will compare values in
-each row according to taht scheme. Here is a complex example on printing a
-table:
-
- from utils import tabulator
-
- runs = [[{"k1": "10", "k2": "12", "k5": "40", "k6": "40",
- "ms_1": "20", "k7": "FAIL", "k8": "PASS", "k9": "PASS",
- "k10": "0"},
- {"k1": "13", "k2": "14", "k3": "15", "ms_1": "10", "k8": "PASS",
- "k9": "FAIL", "k10": "0"}],
- [{"k1": "50", "k2": "51", "k3": "52", "k4": "53", "k5": "35", "k6":
- "45", "ms_1": "200", "ms_2": "20", "k7": "FAIL", "k8": "PASS", "k9":
- "PASS"}]]
- labels = ["vanilla", "modified"]
- tg = TableGenerator(runs, labels, TableGenerator.SORT_BY_VALUES_DESC)
- table = tg.GetTable()
- columns = [Column(LiteralResult(),
- Format(),
- "Literal"),
- Column(AmeanResult(),
- Format()),
- Column(StdResult(),
- Format()),
- Column(CoeffVarResult(),
- CoeffVarFormat()),
- Column(NonEmptyCountResult(),
- Format()),
- Column(AmeanRatioResult(),
- PercentFormat()),
- Column(AmeanRatioResult(),
- RatioFormat()),
- Column(GmeanRatioResult(),
- RatioFormat()),
- Column(PValueResult(),
- PValueFormat()),
- ]
- tf = TableFormatter(table, columns)
- cell_table = tf.GetCellTable()
- tp = TablePrinter(cell_table, out_to)
- print tp.Print()
-
-"""
-
-
-import getpass
-import math
-import sys
-import numpy
-
-import colortrans
-from email_sender import EmailSender
-import misc
-
-
-def _AllFloat(values):
- return all([misc.IsFloat(v) for v in values])
-
-
-def _GetFloats(values):
- return [float(v) for v in values]
-
-
-def _StripNone(results):
- res = []
- for result in results:
- if result is not None:
- res.append(result)
- return res
-
-
-class TableGenerator(object):
- """Creates a table from a list of list of dicts.
-
- The main public function is called GetTable().
- """
- SORT_BY_KEYS = 0
- SORT_BY_KEYS_DESC = 1
- SORT_BY_VALUES = 2
- SORT_BY_VALUES_DESC = 3
-
- MISSING_VALUE = "x"
-
- def __init__(self, d, l, sort=SORT_BY_KEYS, key_name="keys"):
- self._runs = d
- self._labels = l
- self._sort = sort
- self._key_name = key_name
-
- def _AggregateKeys(self):
- keys = set([])
- for run_list in self._runs:
- for run in run_list:
- keys = keys.union(run.keys())
- return keys
-
- def _GetHighestValue(self, key):
- values = []
- for run_list in self._runs:
- for run in run_list:
- if key in run:
- values.append(run[key])
- values = _StripNone(values)
- if _AllFloat(values):
- values = _GetFloats(values)
- return max(values)
-
- def _GetLowestValue(self, key):
- values = []
- for run_list in self._runs:
- for run in run_list:
- if key in run:
- values.append(run[key])
- values = _StripNone(values)
- if _AllFloat(values):
- values = _GetFloats(values)
- return min(values)
-
- def _SortKeys(self, keys):
- if self._sort == self.SORT_BY_KEYS:
- return sorted(keys)
- elif self._sort == self.SORT_BY_VALUES:
- # pylint: disable=unnecessary-lambda
- return sorted(keys, key=lambda x: self._GetLowestValue(x))
- elif self._sort == self.SORT_BY_VALUES_DESC:
- # pylint: disable=unnecessary-lambda
- return sorted(keys, key=lambda x: self._GetHighestValue(x), reverse=True)
- else:
- assert 0, "Unimplemented sort %s" % self._sort
-
- def _GetKeys(self):
- keys = self._AggregateKeys()
- return self._SortKeys(keys)
-
- def GetTable(self, number_of_rows=sys.maxint):
- """Returns a table from a list of list of dicts.
-
- The list of list of dicts is passed into the constructor of TableGenerator.
- This method converts that into a canonical list of lists which represents a
- table of values.
-
- Args:
- number_of_rows: Maximum number of rows to return from the table.
- Returns:
- A list of lists which is the table.
-
- Example:
- We have the following runs:
- [[{"k1": "v1", "k2": "v2"}, {"k1": "v3"}],
- [{"k1": "v4", "k4": "v5"}]]
- and the following labels:
- ["vanilla", "modified"]
- it will return:
- [["Key", "vanilla", "modified"]
- ["k1", ["v1", "v3"], ["v4"]]
- ["k2", ["v2"], []]
- ["k4", [], ["v5"]]]
- The returned table can then be processed further by other classes in this
- module.
- """
- keys = self._GetKeys()
- header = [self._key_name] + self._labels
- table = [header]
- rows = 0
- for k in keys:
- row = [k]
- for run_list in self._runs:
- v = []
- for run in run_list:
- if k in run:
- v.append(run[k])
- else:
- v.append(None)
- row.append(v)
- table.append(row)
- rows += 1
- if rows == number_of_rows:
- break
- return table
-
-
-class Result(object):
- """A class that respresents a single result.
-
- This single result is obtained by condensing the information from a list of
- runs and a list of baseline runs.
- """
-
- def __init__(self):
- pass
-
- def _AllStringsSame(self, values):
- values_set = set(values)
- return len(values_set) == 1
-
- def NeedsBaseline(self):
- return False
-
- # pylint: disable=unused-argument
- def _Literal(self, cell, values, baseline_values):
- cell.value = " ".join([str(v) for v in values])
-
- def _ComputeFloat(self, cell, values, baseline_values):
- self._Literal(cell, values, baseline_values)
-
- def _ComputeString(self, cell, values, baseline_values):
- self._Literal(cell, values, baseline_values)
-
- def _InvertIfLowerIsBetter(self, cell):
- pass
-
- def _GetGmean(self, values):
- if not values:
- return float("nan")
- if any([v < 0 for v in values]):
- return float ("nan")
- if any([v == 0 for v in values]):
- return 0.0
- log_list = [math.log(v) for v in values]
- gmean_log = sum(log_list)/len(log_list)
- return math.exp(gmean_log)
-
- def Compute(self, cell, values, baseline_values):
- """Compute the result given a list of values and baseline values.
-
- Args:
- cell: A cell data structure to populate.
- values: List of values.
- baseline_values: List of baseline values. Can be none if this is the
- baseline itself.
- """
- all_floats = True
- values = _StripNone(values)
- if not values:
- cell.value = ""
- return
- if _AllFloat(values):
- float_values = _GetFloats(values)
- else:
- all_floats = False
- if baseline_values:
- baseline_values = _StripNone(baseline_values)
- if baseline_values:
- if _AllFloat(baseline_values):
- float_baseline_values = _GetFloats(baseline_values)
- else:
- all_floats = False
- else:
- if self.NeedsBaseline():
- cell.value = ""
- return
- float_baseline_values = None
- if all_floats:
- self._ComputeFloat(cell, float_values, float_baseline_values)
- self._InvertIfLowerIsBetter(cell)
- else:
- self._ComputeString(cell, values, baseline_values)
-
-
-class LiteralResult(Result):
- def __init__(self, iteration=0):
- super(LiteralResult, self).__init__()
- self.iteration = iteration
-
- def Compute(self, cell, values, baseline_values):
- try:
- cell.value = values[self.iteration]
- except IndexError:
- cell.value = "-"
-
-
-class NonEmptyCountResult(Result):
- """A class that counts the number of non-empty results.
-
- The number of non-empty values will be stored in the cell.
- """
-
- def Compute(self, cell, values, baseline_values):
- """Put the number of non-empty values in the cell result.
-
- Args:
- cell: Put the result in cell.value.
- values: A list of values for the row.
- baseline_values: A list of baseline values for the row.
- """
- cell.value = len(_StripNone(values))
- if not baseline_values:
- return
- base_value = len(_StripNone(baseline_values))
- if cell.value == base_value:
- return
- f = ColorBoxFormat()
- len_values = len(values)
- len_baseline_values = len(baseline_values)
- tmp_cell = Cell()
- tmp_cell.value = 1.0 + (float(cell.value - base_value) /
- (max(len_values, len_baseline_values)))
- f.Compute(tmp_cell)
- cell.bgcolor = tmp_cell.bgcolor
-
-
-class StringMeanResult(Result):
- def _ComputeString(self, cell, values, baseline_values):
- if self._AllStringsSame(values):
- cell.value = str(values[0])
- else:
- cell.value = "?"
-
-
-class AmeanResult(StringMeanResult):
- def _ComputeFloat(self, cell, values, baseline_values):
- cell.value = numpy.mean(values)
-
-
-class RawResult(Result):
- pass
-
-
-class MinResult(Result):
- def _ComputeFloat(self, cell, values, baseline_values):
- cell.value = min(values)
-
- def _ComputeString(self, cell, values, baseline_values):
- if values:
- cell.value = min(values)
- else:
- cell.value = ""
-
-
-class MaxResult(Result):
- def _ComputeFloat(self, cell, values, baseline_values):
- cell.value = max(values)
-
- def _ComputeString(self, cell, values, baseline_values):
- if values:
- cell.value = max(values)
- else:
- cell.value = ""
-
-
-class NumericalResult(Result):
- def _ComputeString(self, cell, values, baseline_values):
- cell.value = "?"
-
-
-class StdResult(NumericalResult):
- def _ComputeFloat(self, cell, values, baseline_values):
- cell.value = numpy.std(values)
-
-
-class CoeffVarResult(NumericalResult):
- def _ComputeFloat(self, cell, values, baseline_values):
- noise = numpy.abs(numpy.std(values)/numpy.mean(values))
- cell.value = noise
-
-
-class ComparisonResult(Result):
- def NeedsBaseline(self):
- return True
-
- def _ComputeString(self, cell, values, baseline_values):
- value = None
- baseline_value = None
- if self._AllStringsSame(values):
- value = values[0]
- if self._AllStringsSame(baseline_values):
- baseline_value = baseline_values[0]
- if value is not None and baseline_value is not None:
- if value == baseline_value:
- cell.value = "SAME"
- else:
- cell.value = "DIFFERENT"
- else:
- cell.value = "?"
-
-
-class PValueResult(ComparisonResult):
- def _ComputeFloat(self, cell, values, baseline_values):
- if len(values) < 2 or len(baseline_values) < 2:
- cell.value = float("nan")
- return
- import stats # pylint: disable=g-import-not-at-top
- _, cell.value = stats.lttest_ind(values, baseline_values)
-
- def _ComputeString(self, cell, values, baseline_values):
- return float("nan")
-
-
-class KeyAwareComparisonResult(ComparisonResult):
- def _IsLowerBetter(self, key):
- lower_is_better_keys = ["milliseconds", "ms", "seconds", "KB",
- "rdbytes", "wrbytes"]
- return any([key.startswith(l + "_") for l in lower_is_better_keys])
-
- def _InvertIfLowerIsBetter(self, cell):
- if self._IsLowerBetter(cell.name):
- if cell.value:
- cell.value = 1.0/cell.value
-
-
-class AmeanRatioResult(KeyAwareComparisonResult):
- def _ComputeFloat(self, cell, values, baseline_values):
- if numpy.mean(baseline_values) != 0:
- cell.value = numpy.mean(values)/numpy.mean(baseline_values)
- elif numpy.mean(values) != 0:
- cell.value = 0.00
- # cell.value = 0 means the values and baseline_values have big difference
- else:
- cell.value = 1.00
- # no difference if both values and baseline_values are 0
-
-
-class GmeanRatioResult(KeyAwareComparisonResult):
- def _ComputeFloat(self, cell, values, baseline_values):
- if self._GetGmean(baseline_values) != 0:
- cell.value = self._GetGmean(values)/self._GetGmean(baseline_values)
- elif self._GetGmean(values) != 0:
- cell.value = 0.00
- else:
- cell.value = 1.00
-
-
-class Color(object):
- """Class that represents color in RGBA format."""
-
- def __init__(self, r=0, g=0, b=0, a=0):
- self.r = r
- self.g = g
- self.b = b
- self.a = a
-
- def __str__(self):
- return "r: %s g: %s: b: %s: a: %s" % (self.r, self.g, self.b, self.a)
-
- def Round(self):
- """Round RGBA values to the nearest integer."""
- self.r = int(self.r)
- self.g = int(self.g)
- self.b = int(self.b)
- self.a = int(self.a)
-
- def GetRGB(self):
- """Get a hex representation of the color."""
- return "%02x%02x%02x" % (self.r, self.g, self.b)
-
- @classmethod
- def Lerp(cls, ratio, a, b):
- """Perform linear interpolation between two colors.
-
- Args:
- ratio: The ratio to use for linear polation.
- a: The first color object (used when ratio is 0).
- b: The second color object (used when ratio is 1).
-
- Returns:
- Linearly interpolated color.
- """
- ret = cls()
- ret.r = (b.r - a.r)*ratio + a.r
- ret.g = (b.g - a.g)*ratio + a.g
- ret.b = (b.b - a.b)*ratio + a.b
- ret.a = (b.a - a.a)*ratio + a.a
- return ret
-
-
-class Format(object):
- """A class that represents the format of a column."""
-
- def __init__(self):
- pass
-
- def Compute(self, cell):
- """Computes the attributes of a cell based on its value.
-
- Attributes typically are color, width, etc.
-
- Args:
- cell: The cell whose attributes are to be populated.
- """
- if cell.value is None:
- cell.string_value = ""
- if isinstance(cell.value, float):
- self._ComputeFloat(cell)
- else:
- self._ComputeString(cell)
-
- def _ComputeFloat(self, cell):
- cell.string_value = "{0:.2f}".format(cell.value)
-
- def _ComputeString(self, cell):
- cell.string_value = str(cell.value)
-
- def _GetColor(self, value, low, mid, high, power=6, mid_value=1.0):
- min_value = 0.0
- max_value = 2.0
- if math.isnan(value):
- return mid
- if value > mid_value:
- value = max_value - mid_value/value
-
- return self._GetColorBetweenRange(value, min_value, mid_value, max_value,
- low, mid, high, power)
-
- def _GetColorBetweenRange(self,
- value,
- min_value, mid_value, max_value,
- low_color, mid_color, high_color,
- power):
- assert value <= max_value
- assert value >= min_value
- if value > mid_value:
- value = (max_value - value)/(max_value - mid_value)
- value **= power
- ret = Color.Lerp(value, high_color, mid_color)
- else:
- value = (value - min_value)/(mid_value - min_value)
- value **= power
- ret = Color.Lerp(value, low_color, mid_color)
- ret.Round()
- return ret
-
-
-class PValueFormat(Format):
- def _ComputeFloat(self, cell):
- cell.string_value = "%0.2f" % float(cell.value)
- if float(cell.value) < 0.05:
- cell.bgcolor = self._GetColor(cell.value,
- Color(255, 255, 0, 0),
- Color(255, 255, 255, 0),
- Color(255, 255, 255, 0),
- mid_value=0.05,
- power=1)
-
-
-class StorageFormat(Format):
- """Format the cell as a storage number.
-
- Example:
- If the cell contains a value of 1024, the string_value will be 1.0K.
- """
-
- def _ComputeFloat(self, cell):
- base = 1024
- suffices = ["K", "M", "G"]
- v = float(cell.value)
- current = 0
- while v >= base**(current + 1) and current < len(suffices):
- current += 1
-
- if current:
- divisor = base**current
- cell.string_value = "%1.1f%s" % ((v/divisor), suffices[current - 1])
- else:
- cell.string_value = str(cell.value)
-
-
-class CoeffVarFormat(Format):
- """Format the cell as a percent.
-
- Example:
- If the cell contains a value of 1.5, the string_value will be +150%.
- """
-
- def _ComputeFloat(self, cell):
- cell.string_value = "%1.1f%%" % (float(cell.value) * 100)
- cell.color = self._GetColor(cell.value,
- Color(0, 255, 0, 0),
- Color(0, 0, 0, 0),
- Color(255, 0, 0, 0),
- mid_value=0.02,
- power=1)
-
-
-class PercentFormat(Format):
- """Format the cell as a percent.
-
- Example:
- If the cell contains a value of 1.5, the string_value will be +50%.
- """
-
- def _ComputeFloat(self, cell):
- cell.string_value = "%+1.1f%%" % ((float(cell.value) - 1) * 100)
- cell.color = self._GetColor(cell.value,
- Color(255, 0, 0, 0),
- Color(0, 0, 0, 0),
- Color(0, 255, 0, 0))
-
-
-class RatioFormat(Format):
- """Format the cell as a ratio.
-
- Example:
- If the cell contains a value of 1.5642, the string_value will be 1.56.
- """
-
- def _ComputeFloat(self, cell):
- cell.string_value = "%+1.1f%%" % ((cell.value - 1) * 100)
- cell.color = self._GetColor(cell.value,
- Color(255, 0, 0, 0),
- Color(0, 0, 0, 0),
- Color(0, 255, 0, 0))
-
-
-class ColorBoxFormat(Format):
- """Format the cell as a color box.
-
- Example:
- If the cell contains a value of 1.5, it will get a green color.
- If the cell contains a value of 0.5, it will get a red color.
- The intensity of the green/red will be determined by how much above or below
- 1.0 the value is.
- """
-
- def _ComputeFloat(self, cell):
- cell.string_value = "--"
- bgcolor = self._GetColor(cell.value,
- Color(255, 0, 0, 0),
- Color(255, 255, 255, 0),
- Color(0, 255, 0, 0))
- cell.bgcolor = bgcolor
- cell.color = bgcolor
-
-
-class Cell(object):
- """A class to represent a cell in a table.
-
- Attributes:
- value: The raw value of the cell.
- color: The color of the cell.
- bgcolor: The background color of the cell.
- string_value: The string value of the cell.
- suffix: A string suffix to be attached to the value when displaying.
- prefix: A string prefix to be attached to the value when displaying.
- color_row: Indicates whether the whole row is to inherit this cell's color.
- bgcolor_row: Indicates whether the whole row is to inherit this cell's
- bgcolor.
- width: Optional specifier to make a column narrower than the usual width.
- The usual width of a column is the max of all its cells widths.
- colspan: Set the colspan of the cell in the HTML table, this is used for
- table headers. Default value is 1.
- name: the test name of the cell.
- header: Whether this is a header in html.
- """
-
- def __init__(self):
- self.value = None
- self.color = None
- self.bgcolor = None
- self.string_value = None
- self.suffix = None
- self.prefix = None
- # Entire row inherits this color.
- self.color_row = False
- self.bgcolor_row = False
- self.width = None
- self.colspan = 1
- self.name = None
- self.header = False
-
- def __str__(self):
- l = []
- l.append("value: %s" % self.value)
- l.append("string_value: %s" % self.string_value)
- return " ".join(l)
-
-
-class Column(object):
- """Class representing a column in a table.
-
- Attributes:
- result: an object of the Result class.
- fmt: an object of the Format class.
- """
-
- def __init__(self, result, fmt, name=""):
- self.result = result
- self.fmt = fmt
- self.name = name
-
-
-# Takes in:
-# ["Key", "Label1", "Label2"]
-# ["k", ["v", "v2"], [v3]]
-# etc.
-# Also takes in a format string.
-# Returns a table like:
-# ["Key", "Label1", "Label2"]
-# ["k", avg("v", "v2"), stddev("v", "v2"), etc.]]
-# according to format string
-class TableFormatter(object):
- """Class to convert a plain table into a cell-table.
-
- This class takes in a table generated by TableGenerator and a list of column
- formats to apply to the table and returns a table of cells.
- """
-
- def __init__(self, table, columns):
- """The constructor takes in a table and a list of columns.
-
- Args:
- table: A list of lists of values.
- columns: A list of column containing what to produce and how to format it.
- """
- self._table = table
- self._columns = columns
- self._table_columns = []
- self._out_table = []
-
- def GenerateCellTable(self):
- row_index = 0
-
- for row in self._table[1:]:
- key = Cell()
- key.string_value = str(row[0])
- out_row = [key]
- baseline = None
- for values in row[1:]:
- for column in self._columns:
- cell = Cell()
- cell.name = key.string_value
- if column.result.NeedsBaseline():
- if baseline is not None:
- column.result.Compute(cell, values, baseline)
- column.fmt.Compute(cell)
- out_row.append(cell)
- if not row_index:
- self._table_columns.append(column)
- else:
- column.result.Compute(cell, values, baseline)
- column.fmt.Compute(cell)
- out_row.append(cell)
- if not row_index:
- self._table_columns.append(column)
-
- if baseline is None:
- baseline = values
- self._out_table.append(out_row)
- row_index += 1
-
- def AddColumnName(self):
- """Generate Column name at the top of table."""
- key = Cell()
- key.header = True
- key.string_value = "Keys"
- header = [key]
- for column in self._table_columns:
- cell = Cell()
- cell.header = True
- if column.name:
- cell.string_value = column.name
- else:
- result_name = column.result.__class__.__name__
- format_name = column.fmt.__class__.__name__
-
- cell.string_value = "%s %s" % (result_name.replace("Result", ""),
- format_name.replace("Format", ""))
-
- header.append(cell)
-
- self._out_table = [header] + self._out_table
-
- def AddHeader(self, s):
- """Put additional string on the top of the table."""
- cell = Cell()
- cell.header = True
- cell.string_value = str(s)
- header = [cell]
- colspan = max(1, max(len(row) for row in self._table))
- cell.colspan = colspan
- self._out_table = [header] + self._out_table
-
- def AddLabelName(self):
- """Put label on the top of the table."""
- top_header = []
- base_colspan = len([c for c in self._columns
- if not c.result.NeedsBaseline()])
- compare_colspan = len(self._columns)
- # The label is organized as follows
- # "keys" label_base, label_comparison1, label_comparison2
- # The first cell has colspan 1, the second is base_colspan
- # The others are compare_colspan
- for label in self._table[0]:
- cell = Cell()
- cell.header = True
- cell.string_value = str(label)
- if top_header:
- cell.colspan = base_colspan
- if len(top_header) > 1:
- cell.colspan = compare_colspan
- top_header.append(cell)
- self._out_table = [top_header] + self._out_table
-
- def _PrintOutTable(self):
- o = ""
- for row in self._out_table:
- for cell in row:
- o += str(cell) + " "
- o += "\n"
- print o
-
- def GetCellTable(self, headers=True):
- """Function to return a table of cells.
-
- The table (list of lists) is converted into a table of cells by this
- function.
- Args:
- headers: A boolean saying whether we want default headers
-
- Returns:
- A table of cells with each cell having the properties and string values as
- requiested by the columns passed in the constructor.
- """
- # Generate the cell table, creating a list of dynamic columns on the fly.
- if not self._out_table:
- self.GenerateCellTable()
- if headers:
- self.AddColumnName()
- self.AddLabelName()
- return self._out_table
-
-
-class TablePrinter(object):
- """Class to print a cell table to the console, file or html."""
- PLAIN = 0
- CONSOLE = 1
- HTML = 2
- TSV = 3
- EMAIL = 4
-
- def __init__(self, table, output_type):
- """Constructor that stores the cell table and output type."""
- self._table = table
- self._output_type = output_type
-
- # Compute whole-table properties like max-size, etc.
- def _ComputeStyle(self):
- self._row_styles = []
- for row in self._table:
- row_style = Cell()
- for cell in row:
- if cell.color_row:
- assert cell.color, "Cell color not set but color_row set!"
- assert not row_style.color, "Multiple row_style.colors found!"
- row_style.color = cell.color
- if cell.bgcolor_row:
- assert cell.bgcolor, "Cell bgcolor not set but bgcolor_row set!"
- assert not row_style.bgcolor, "Multiple row_style.bgcolors found!"
- row_style.bgcolor = cell.bgcolor
- self._row_styles.append(row_style)
-
- self._column_styles = []
- if len(self._table) < 2:
- return
-
- for i in range(max(len(row) for row in self._table)):
- column_style = Cell()
- for row in self._table:
- if not any([cell.colspan != 1 for cell in row]):
- column_style.width = max(column_style.width,
- len(row[i].string_value))
- self._column_styles.append(column_style)
-
- def _GetBGColorFix(self, color):
- if self._output_type == self.CONSOLE:
- rgb = color.GetRGB()
- prefix, _ = colortrans.rgb2short(rgb)
- # pylint: disable=anomalous-backslash-in-string
- prefix = "\033[48;5;%sm" % prefix
- suffix = "\033[0m"
- elif self._output_type in [self.EMAIL, self.HTML]:
- rgb = color.GetRGB()
- prefix = ("<FONT style=\"BACKGROUND-COLOR:#{0}\">"
- .format(rgb))
- suffix = "</FONT>"
- elif self._output_type in [self.PLAIN, self.TSV]:
- prefix = ""
- suffix = ""
- return prefix, suffix
-
- def _GetColorFix(self, color):
- if self._output_type == self.CONSOLE:
- rgb = color.GetRGB()
- prefix, _ = colortrans.rgb2short(rgb)
- # pylint: disable=anomalous-backslash-in-string
- prefix = "\033[38;5;%sm" % prefix
- suffix = "\033[0m"
- elif self._output_type in [self.EMAIL, self.HTML]:
- rgb = color.GetRGB()
- prefix = "<FONT COLOR=#{0}>".format(rgb)
- suffix = "</FONT>"
- elif self._output_type in [self.PLAIN, self.TSV]:
- prefix = ""
- suffix = ""
- return prefix, suffix
-
- def Print(self):
- """Print the table to a console, html, etc.
-
- Returns:
- A string that contains the desired representation of the table.
- """
- self._ComputeStyle()
- return self._GetStringValue()
-
- def _GetCellValue(self, i, j):
- cell = self._table[i][j]
- out = cell.string_value
- raw_width = len(out)
-
- if cell.color:
- p, s = self._GetColorFix(cell.color)
- out = "%s%s%s" % (p, out, s)
-
- if cell.bgcolor:
- p, s = self._GetBGColorFix(cell.bgcolor)
- out = "%s%s%s" % (p, out, s)
-
- if self._output_type in [self.PLAIN, self.CONSOLE, self.EMAIL]:
- if cell.width:
- width = cell.width
- else:
- if self._column_styles:
- width = self._column_styles[j].width
- else:
- width = len(cell.string_value)
- if cell.colspan > 1:
- width = 0
- start = 0
- for k in range(j):
- start += self._table[i][k].colspan
- for k in range(cell.colspan):
- width += self._column_styles[start + k].width
- if width > raw_width:
- padding = ("%" + str(width - raw_width) + "s") % ""
- out = padding + out
-
- if self._output_type == self.HTML:
- if cell.header:
- tag = "th"
- else:
- tag = "td"
- out = "<{0} colspan = \"{2}\"> {1} </{0}>".format(tag, out, cell.colspan)
-
- return out
-
- def _GetHorizontalSeparator(self):
- if self._output_type in [self.CONSOLE, self.PLAIN, self.EMAIL]:
- return " "
- if self._output_type == self.HTML:
- return ""
- if self._output_type == self.TSV:
- return "\t"
-
- def _GetVerticalSeparator(self):
- if self._output_type in [self.PLAIN, self.CONSOLE, self.TSV, self.EMAIL]:
- return "\n"
- if self._output_type == self.HTML:
- return "</tr>\n<tr>"
-
- def _GetPrefix(self):
- if self._output_type in [self.PLAIN, self.CONSOLE, self.TSV, self.EMAIL]:
- return ""
- if self._output_type == self.HTML:
- return "<p></p><table id=\"box-table-a\">\n<tr>"
-
- def _GetSuffix(self):
- if self._output_type in [self.PLAIN, self.CONSOLE, self.TSV, self.EMAIL]:
- return ""
- if self._output_type == self.HTML:
- return "</tr>\n</table>"
-
- def _GetStringValue(self):
- o = ""
- o += self._GetPrefix()
- for i in range(len(self._table)):
- row = self._table[i]
- # Apply row color and bgcolor.
- p = s = bgp = bgs = ""
- if self._row_styles[i].bgcolor:
- bgp, bgs = self._GetBGColorFix(self._row_styles[i].bgcolor)
- if self._row_styles[i].color:
- p, s = self._GetColorFix(self._row_styles[i].color)
- o += p + bgp
- for j in range(len(row)):
- out = self._GetCellValue(i, j)
- o += out + self._GetHorizontalSeparator()
- o += s + bgs
- o += self._GetVerticalSeparator()
- o += self._GetSuffix()
- return o
-
-
-# Some common drivers
-def GetSimpleTable(table, out_to=TablePrinter.CONSOLE):
- """Prints a simple table.
-
- This is used by code that has a very simple list-of-lists and wants to produce
- a table with ameans, a percentage ratio of ameans and a colorbox.
-
- Args:
- table: a list of lists.
- out_to: specify the fomat of output. Currently it supports HTML and CONSOLE.
-
- Returns:
- A string version of the table that can be printed to the console.
-
- Example:
- GetSimpleConsoleTable([["binary", "b1", "b2"],["size", "300", "400"]])
- will produce a colored table that can be printed to the console.
- """
- columns = [
- Column(AmeanResult(),
- Format()),
- Column(AmeanRatioResult(),
- PercentFormat()),
- Column(AmeanRatioResult(),
- ColorBoxFormat()),
- ]
- our_table = [table[0]]
- for row in table[1:]:
- our_row = [row[0]]
- for v in row[1:]:
- our_row.append([v])
- our_table.append(our_row)
-
- tf = TableFormatter(our_table, columns)
- cell_table = tf.GetCellTable()
- tp = TablePrinter(cell_table, out_to)
- return tp.Print()
-
-
-# pylint: disable=redefined-outer-name
-def GetComplexTable(runs, labels, out_to=TablePrinter.CONSOLE):
- """Prints a complex table.
-
- This can be used to generate a table with arithmetic mean, standard deviation,
- coefficient of variation, p-values, etc.
-
- Args:
- runs: A list of lists with data to tabulate.
- labels: A list of labels that correspond to the runs.
- out_to: specifies the format of the table (example CONSOLE or HTML).
-
- Returns:
- A string table that can be printed to the console or put in an HTML file.
- """
- tg = TableGenerator(runs, labels, TableGenerator.SORT_BY_VALUES_DESC)
- table = tg.GetTable()
- columns = [Column(LiteralResult(),
- Format(),
- "Literal"),
- Column(AmeanResult(),
- Format()),
- Column(StdResult(),
- Format()),
- Column(CoeffVarResult(),
- CoeffVarFormat()),
- Column(NonEmptyCountResult(),
- Format()),
- Column(AmeanRatioResult(),
- PercentFormat()),
- Column(AmeanRatioResult(),
- RatioFormat()),
- Column(GmeanRatioResult(),
- RatioFormat()),
- Column(PValueResult(),
- PValueFormat()),
- ]
- tf = TableFormatter(table, columns)
- cell_table = tf.GetCellTable()
- tp = TablePrinter(cell_table, out_to)
- return tp.Print()
-
-if __name__ == "__main__":
- # Run a few small tests here.
- runs = [[{"k1": "10", "k2": "12", "k5": "40", "k6": "40",
- "ms_1": "20", "k7": "FAIL", "k8": "PASS", "k9": "PASS",
- "k10": "0"},
- {"k1": "13", "k2": "14", "k3": "15", "ms_1": "10", "k8": "PASS",
- "k9": "FAIL", "k10": "0"}],
- [{"k1": "50", "k2": "51", "k3": "52", "k4": "53", "k5": "35", "k6":
- "45", "ms_1": "200", "ms_2": "20", "k7": "FAIL", "k8": "PASS", "k9":
- "PASS"}]]
- labels = ["vanilla", "modified"]
- t = GetComplexTable(runs, labels, TablePrinter.CONSOLE)
- print t
- email = GetComplexTable(runs, labels, TablePrinter.EMAIL)
-
- runs = [[{"k1": "1"}, {"k1": "1.1"}, {"k1": "1.2"}],
- [{"k1": "5"}, {"k1": "5.1"}, {"k1": "5.2"}]]
- t = GetComplexTable(runs, labels, TablePrinter.CONSOLE)
- print t
-
- simple_table = [
- ["binary", "b1", "b2", "b3"],
- ["size", 100, 105, 108],
- ["rodata", 100, 80, 70],
- ["data", 100, 100, 100],
- ["debug", 100, 140, 60],
- ]
- t = GetSimpleTable(simple_table)
- print t
- email += GetSimpleTable(simple_table, TablePrinter.HTML)
- email_to = [getpass.getuser()]
- email = "<pre style='font-size: 13px'>%s</pre>" % email
- EmailSender().SendEmail(email_to, "SimpleTableTest", email, msg_type="html")
diff --git a/v14/utils/tabulator_test.py b/v14/utils/tabulator_test.py
deleted file mode 100644
index 16406107..00000000
--- a/v14/utils/tabulator_test.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# Copyright 2012 Google Inc. All Rights Reserved.
-
-"""Tests for the tabulator module."""
-
-__author__ = "asharif@google.com (Ahmad Sharif)"
-
-# System modules
-import unittest
-
-# Local modules
-import tabulator
-
-
-class TabulatorTest(unittest.TestCase):
- def testResult(self):
- table = ["k1", ["1", "3"], ["55"]]
- result = tabulator.Result()
- cell = tabulator.Cell()
- result.Compute(cell, table[2], table[1])
- expected = " ".join([str(float(v)) for v in table[2]])
- self.assertTrue(cell.value == expected)
-
- result = tabulator.AmeanResult()
- cell = tabulator.Cell()
- result.Compute(cell, table[2], table[1])
- self.assertTrue(cell.value == float(table[2][0]))
-
- def testStringMean(self):
- smr = tabulator.StringMeanResult()
- cell = tabulator.Cell()
- value = "PASS"
- values = [value for _ in range(3)]
- smr.Compute(cell, values, None)
- self.assertTrue(cell.value == value)
- values.append("FAIL")
- smr.Compute(cell, values, None)
- self.assertTrue(cell.value == "?")
-
- def testStorageFormat(self):
- sf = tabulator.StorageFormat()
- cell = tabulator.Cell()
- base = 1024.0
- cell.value = base
- sf.Compute(cell)
- self.assertTrue(cell.string_value == "1.0K")
- cell.value = base**2
- sf.Compute(cell)
- self.assertTrue(cell.string_value == "1.0M")
- cell.value = base**3
- sf.Compute(cell)
- self.assertTrue(cell.string_value == "1.0G")
-
- def testLerp(self):
- c1 = tabulator.Color(0, 0, 0, 0)
- c2 = tabulator.Color(255, 0, 0, 0)
- c3 = tabulator.Color.Lerp(0.5, c1, c2)
- self.assertTrue(c3.r == 127.5)
- self.assertTrue(c3.g == 0)
- self.assertTrue(c3.b == 0)
- self.assertTrue(c3.a == 0)
- c3.Round()
- self.assertTrue(c3.r == 127)
-
- def testGmean(self):
- a = [1.0e+308] * 3
- b = tabulator.Result()._GetGmean(a)
- self.assertTrue(b >= 0.99e+308 and b <= 1.01e+308)
-
- def testTableGenerator(self):
- runs = [[{"k1": "10", "k2": "12"},
- {"k1": "13", "k2": "14", "k3": "15"}],
- [{"k1": "50", "k2": "51", "k3": "52", "k4": "53"}]]
- labels = ["vanilla", "modified"]
- tg = tabulator.TableGenerator(runs, labels)
- table = tg.GetTable()
- header = table.pop(0)
-
- self.assertTrue(header == ["keys", "vanilla", "modified"])
- row = table.pop(0)
- self.assertTrue(row == ["k1", ["10", "13"], ["50"]])
- row = table.pop(0)
- self.assertTrue(row == ["k2", ["12", "14"], ["51"]])
- row = table.pop(0)
- self.assertTrue(row == ["k3", [None, "15"], ["52"]])
- row = table.pop(0)
- self.assertTrue(row == ["k4", [None, None], ["53"]])
-
- table = tg.GetTable()
- columns = [
- tabulator.Column(tabulator.AmeanResult(),
- tabulator.Format()),
- tabulator.Column(tabulator.AmeanRatioResult(),
- tabulator.PercentFormat()),
- ]
- tf = tabulator.TableFormatter(table, columns)
- table = tf.GetCellTable()
- self.assertTrue(table)
-
- def testColspan(self):
- simple_table = [
- ["binary", "b1", "b2", "b3"],
- ["size", 100, 105, 108],
- ["rodata", 100, 80, 70],
- ["data", 100, 100, 100],
- ["debug", 100, 140, 60],
- ]
- columns = [
- tabulator.Column(tabulator.AmeanResult(),
- tabulator.Format()),
- tabulator.Column(tabulator.MinResult(),
- tabulator.Format()),
- tabulator.Column(tabulator.AmeanRatioResult(),
- tabulator.PercentFormat()),
- tabulator.Column(tabulator.AmeanRatioResult(),
- tabulator.ColorBoxFormat()),
- ]
- our_table = [simple_table[0]]
- for row in simple_table[1:]:
- our_row = [row[0]]
- for v in row[1:]:
- our_row.append([v])
- our_table.append(our_row)
-
- tf = tabulator.TableFormatter(our_table, columns)
- cell_table = tf.GetCellTable()
- self.assertTrue(cell_table[0][0].colspan == 1)
- self.assertTrue(cell_table[0][1].colspan == 2)
- self.assertTrue(cell_table[0][2].colspan == 4)
- self.assertTrue(cell_table[0][3].colspan == 4)
- for row in cell_table[1:]:
- for cell in row:
- self.assertTrue(cell.colspan == 1)
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/v14/utils/timeline.py b/v14/utils/timeline.py
deleted file mode 100644
index fa75ba01..00000000
--- a/v14/utils/timeline.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/python2.6
-#
-# Copyright 2012 Google Inc. All Rights Reserved.
-#
-
-"""Tools for recording and reporting timeline of benchmark_run."""
-
-__author__ = 'yunlian@google.com (Yunlian Jiang)'
-
-import time
-
-
-class Event(object):
- def __init__(self, name='', cur_time=0):
- self.name = name
- self.timestamp = cur_time
-
-
-class Timeline(object):
- """Use a dict to store the timeline."""
-
- def __init__(self):
- self.events = []
-
- def Record(self, event):
- for e in self.events:
- assert e.name != event, ('The event {0} is already recorded.'
- .format(event))
- cur_event = Event(name=event, cur_time=time.time())
- self.events.append(cur_event)
-
- def GetEvents(self):
- return([e.name for e in self.events])
-
- def GetEventDict(self):
- tl = {}
- for e in self.events:
- tl[e.name] = e.timestamp
- return tl
-
- def GetEventTime(self, event):
- for e in self.events:
- if e.name == event:
- return e.timestamp
- raise IndexError, 'The event {0} is not recorded'.format(event)
-
- def GetLastEventTime(self):
- return self.events[-1].timestamp
-
- def GetLastEvent(self):
- return self.events[-1].name
diff --git a/v14/utils/timeline_test.py b/v14/utils/timeline_test.py
deleted file mode 100644
index 1f4d178a..00000000
--- a/v14/utils/timeline_test.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright 2012 Google Inc. All Rights Reserved.
-
-"""Tests for time_line.py."""
-
-__author__ = 'yunlian@google.com (Yunlian Jiang)'
-
-import time
-import unittest
-
-import timeline
-
-
-class TimeLineTest(unittest.TestCase):
-
- def testRecord(self):
- tl = timeline.Timeline()
- tl.Record('A')
- t = time.time()
- t1 = tl.events[0].timestamp
- self.assertEqual(int(t1-t), 0)
- self.assertRaises(AssertionError, tl.Record, 'A')
-
- def testGetEvents(self):
- tl = timeline.Timeline()
- tl.Record('A')
- e = tl.GetEvents()
- self.assertEqual(e, ['A'])
- tl.Record('B')
- e = tl.GetEvents()
- self.assertEqual(e, ['A', 'B'])
-
- def testGetEventTime(self):
- tl = timeline.Timeline()
- tl.Record('A')
- t = time.time()
- t1 = tl.GetEventTime('A')
- self.assertEqual(int(t1-t), 0)
- self.assertRaises(IndexError, tl.GetEventTime, 'B')
-
- def testGetLastEventTime(self):
- tl = timeline.Timeline()
- self.assertRaises(IndexError, tl.GetLastEventTime)
- tl.Record('A')
- t = time.time()
- t1 = tl.GetLastEventTime()
- self.assertEqual(int(t1-t), 0)
- time.sleep(2)
- tl.Record('B')
- t = time.time()
- t1 = tl.GetLastEventTime()
- self.assertEqual(int(t1-t), 0)
-
-if __name__ == '__main__':
- unittest.main()